Annotation of src/usr.bin/tic/dump_entry.c, Revision 1.2
1.2 ! millert 1: /* $OpenBSD$ */
! 2:
1.1 millert 3: /****************************************************************************
4: * Copyright (c) 1998 Free Software Foundation, Inc. *
5: * *
6: * Permission is hereby granted, free of charge, to any person obtaining a *
7: * copy of this software and associated documentation files (the *
8: * "Software"), to deal in the Software without restriction, including *
9: * without limitation the rights to use, copy, modify, merge, publish, *
10: * distribute, distribute with modifications, sublicense, and/or sell *
11: * copies of the Software, and to permit persons to whom the Software is *
12: * furnished to do so, subject to the following conditions: *
13: * *
14: * The above copyright notice and this permission notice shall be included *
15: * in all copies or substantial portions of the Software. *
16: * *
17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
18: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
19: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
20: * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
21: * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
22: * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
23: * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
24: * *
25: * Except as contained in this notice, the name(s) of the above copyright *
26: * holders shall not be used in advertising or otherwise to promote the *
27: * sale, use or other dealings in this Software without prior written *
28: * authorization. *
29: ****************************************************************************/
30:
31: /****************************************************************************
32: * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
33: * and: Eric S. Raymond <esr@snark.thyrsus.com> *
34: ****************************************************************************/
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.2 ! millert 43: MODULE_ID("$From: dump_entry.c,v 1.29 1998/09/26 13:15:00 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:
79: #if NO_LEAKS
80: void _nc_leaks_dump_entry(void)
81: {
82: if (outbuf != 0) {
83: free(outbuf);
84: outbuf = 0;
85: }
86: }
87: #endif
88:
89: NCURSES_CONST char *nametrans(const char *name)
90: /* translate a capability name from termcap to terminfo */
91: {
92: const struct name_table_entry *np;
93:
94: if ((np = _nc_find_entry(name, _nc_info_hash_table)) != 0)
95: switch(np->nte_type)
96: {
97: case BOOLEAN:
98: if (bool_from_termcap[np->nte_index])
99: return(boolcodes[np->nte_index]);
100: break;
101:
102: case NUMBER:
103: if (num_from_termcap[np->nte_index])
104: return(numcodes[np->nte_index]);
105: break;
106:
107: case STRING:
108: if (str_from_termcap[np->nte_index])
109: return(strcodes[np->nte_index]);
110: break;
111: }
112:
113: return(0);
114: }
115:
116: void dump_init(const char *version, int mode, int sort, int twidth, int traceval, bool formatted)
117: /* set up for entry display */
118: {
119: width = twidth;
120: pretty = formatted;
121: tracelevel = traceval;
122:
123: /* versions */
124: if (version == 0)
125: tversion = V_ALLCAPS;
126: else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1")
127: || !strcmp(version, "Ultrix"))
128: tversion = V_SVR1;
129: else if (!strcmp(version, "HP"))
130: tversion = V_HPUX;
131: else if (!strcmp(version, "AIX"))
132: tversion = V_AIX;
133: else if (!strcmp(version, "BSD"))
134: tversion = V_BSD;
135: else
136: tversion = V_ALLCAPS;
137:
138: /* implement display modes */
139: switch (outform = mode)
140: {
141: case F_LITERAL:
142: case F_TERMINFO:
143: bool_names = boolnames;
144: num_names = numnames;
145: str_names = strnames;
146: separator = twidth ? ", " : ",";
147: trailer = "\n\t";
148: break;
149:
150: case F_VARIABLE:
151: bool_names = boolfnames;
152: num_names = numfnames;
153: str_names = strfnames;
154: separator = twidth ? ", " : ",";
155: trailer = "\n\t";
156: break;
157:
158: case F_TERMCAP:
159: case F_TCONVERR:
160: bool_names = boolcodes;
161: num_names = numcodes;
162: str_names = strcodes;
163: separator = ":";
164: trailer = "\\\n\t:";
165: break;
166: }
167:
168: /* implement sort modes */
169: switch(sortmode = sort)
170: {
171: case S_NOSORT:
172: if (traceval)
173: (void) fprintf(stderr,
174: "%s: sorting by term structure order\n", _nc_progname);
175: break;
176:
177: case S_TERMINFO:
178: if (traceval)
179: (void) fprintf(stderr,
180: "%s: sorting by terminfo name order\n", _nc_progname);
181: bool_indirect = bool_terminfo_sort;
182: num_indirect = num_terminfo_sort;
183: str_indirect = str_terminfo_sort;
184: break;
185:
186: case S_VARIABLE:
187: if (traceval)
188: (void) fprintf(stderr,
189: "%s: sorting by C variable order\n", _nc_progname);
190: bool_indirect = bool_variable_sort;
191: num_indirect = num_variable_sort;
192: str_indirect = str_variable_sort;
193: break;
194:
195: case S_TERMCAP:
196: if (traceval)
197: (void) fprintf(stderr,
198: "%s: sorting by termcap name order\n", _nc_progname);
199: bool_indirect = bool_termcap_sort;
200: num_indirect = num_termcap_sort;
201: str_indirect = str_termcap_sort;
202: break;
203: }
204:
205: if (traceval)
206: (void) fprintf(stderr,
207: "%s: width = %d, tversion = %d, outform = %d\n",
208: _nc_progname, width, tversion, outform);
209: }
210:
211: static TERMTYPE *cur_type;
212:
213: static int dump_predicate(int type, int idx)
214: /* predicate function to use for ordinary decompilation */
215: {
216: switch(type) {
217: case BOOLEAN:
218: return (cur_type->Booleans[idx] == FALSE)
219: ? FAIL : cur_type->Booleans[idx];
220:
221: case NUMBER:
222: return (cur_type->Numbers[idx] == ABSENT_NUMERIC)
223: ? FAIL : cur_type->Numbers[idx];
224:
225: case STRING:
226: return (cur_type->Strings[idx] != ABSENT_STRING)
227: ? (int)TRUE : FAIL;
228: }
229:
230: return(FALSE); /* pacify compiler */
231: }
232:
233: static void set_obsolete_termcaps(TERMTYPE *tp);
234: static void repair_acsc(TERMTYPE *tp);
235:
236: /* is this the index of a function key string? */
237: #define FNKEY(i) (((i)<= 65 && (i)>= 75) || ((i)<= 216 && (i)>= 268))
238:
239: static bool version_filter(int type, int idx)
240: /* filter out capabilities we may want to suppress */
241: {
242: switch (tversion)
243: {
244: case V_ALLCAPS: /* SVr4, XSI Curses */
245: return(TRUE);
246:
247: case V_SVR1: /* System V Release 1, Ultrix */
248: switch (type)
249: {
250: case BOOLEAN:
251: /* below and including xon_xoff */
252: return ((idx <= 20) ? TRUE : FALSE);
253: case NUMBER:
254: /* below and including width_status_line */
255: return ((idx <= 7) ? TRUE : FALSE);
256: case STRING:
257: /* below and including prtr_non */
258: return ((idx <= 144) ? TRUE : FALSE);
259: }
260: break;
261:
262: case V_HPUX: /* Hewlett-Packard */
263: switch (type)
264: {
265: case BOOLEAN:
266: /* below and including xon_xoff */
267: return ((idx <= 20) ? TRUE : FALSE);
268: case NUMBER:
269: /* below and including label_width */
270: return ((idx <= 10) ? TRUE : FALSE);
271: case STRING:
272: if (idx <= 144) /* below and including prtr_non */
273: return(TRUE);
274: else if (FNKEY(idx)) /* function keys */
275: return(TRUE);
276: else if (idx==147||idx==156||idx==157) /* plab_norm,label_on,label_off */
277: return(TRUE);
278: else
279: return(FALSE);
280: }
281: break;
282:
283: case V_AIX: /* AIX */
284: switch (type)
285: {
286: case BOOLEAN:
287: /* below and including xon_xoff */
288: return ((idx <= 20) ? TRUE : FALSE);
289: case NUMBER:
290: /* below and including width_status_line */
291: return ((idx <= 7) ? TRUE : FALSE);
292: case STRING:
293: if (idx <= 144) /* below and including prtr_non */
294: return(TRUE);
295: else if (FNKEY(idx)) /* function keys */
296: return(TRUE);
297: else
298: return(FALSE);
299: }
300: break;
301:
302: case V_BSD: /* BSD */
303: switch (type)
304: {
305: case BOOLEAN:
306: return bool_from_termcap[idx];
307: case NUMBER:
308: return num_from_termcap[idx];
309: case STRING:
310: return str_from_termcap[idx];
311: }
312: break;
313: }
314:
315: return(FALSE); /* pacify the compiler */
316: }
317:
318: static
319: void append_output (const char *src)
320: {
321: if (src == 0) {
322: out_used = 0;
323: append_output("");
324: } else {
325: size_t need = strlen(src);
326: size_t want = need + out_used + 1;
327: if (want > out_size) {
328: out_size += want; /* be generous */
329: if (outbuf == 0)
330: outbuf = malloc(out_size);
331: else
332: outbuf = realloc(outbuf, out_size);
333: }
334: (void)strcpy(outbuf + out_used, src);
335: out_used += need;
336: }
337: }
338:
339: static
340: void force_wrap(void)
341: {
342: oldcol = column;
343: append_output(trailer);
344: column = INDENT;
345: }
346:
347: static
348: void wrap_concat(const char *src)
349: {
350: int need = strlen(src);
351: int want = strlen(separator) + need;
352:
353: if (column > INDENT
354: && column + want > width) {
355: force_wrap();
356: }
357: append_output(src);
358: append_output(separator);
359: column += need;
360: }
361:
362: #define IGNORE_SEP_TRAIL(first,last,sep_trail) \
363: if ((size_t)(last - first) > sizeof(sep_trail)-1 \
364: && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \
365: first += sizeof(sep_trail)-2
366:
367: /* Returns the nominal length of the buffer assuming it is termcap format,
368: * i.e., the continuation sequence is treated as a single character ":".
369: *
370: * There are several implementations of termcap which read the text into a
371: * fixed-size buffer. Generally they strip the newlines from the text, but may
372: * not do it until after the buffer is read. Also, "tc=" resolution may be
373: * expanded in the same buffer. This function is useful for measuring the size
374: * of the best fixed-buffer implementation; the worst case may be much worse.
375: */
376: #ifdef TEST_TERMCAP_LENGTH
377: static int termcap_length(const char *src)
378: {
379: static const char pattern[] = ":\\\n\t:";
380:
381: int len = 0;
382: const char *const t = src + strlen(src);
383:
384: while (*src != '\0') {
385: IGNORE_SEP_TRAIL(src, t, pattern);
386: src++;
387: len++;
388: }
389: return len;
390: }
391: #else
392: #define termcap_length(src) strlen(src)
393: #endif
394:
395: static char * fmt_complex(char *dst, char *src, int level)
396: {
397: int percent = 0;
398: int n;
399:
400: dst += strlen(dst);
401: while (*src != '\0') {
402: switch (*src) {
403: case '\\':
404: percent = 0;
405: *dst++ = *src++;
406: break;
407: case '%':
408: percent = 1;
409: break;
410: case '?': /* "if" */
411: case 't': /* "then" */
412: case 'e': /* "else" */
413: if (percent) {
414: percent = 0;
415: dst[-1] = '\n';
416: for (n = 0; n <= level; n++)
417: *dst++ = '\t';
418: *dst++ = '%';
419: *dst++ = *src;
420: *dst = '\0';
421: if (*src++ == '?') {
422: src = fmt_complex(dst, src, level+1);
423: dst += strlen(dst);
424: } else if (level == 1) {
425: _nc_warning("%%%c without %%?", *src);
426: }
427: continue;
428: }
429: break;
430: case ';': /* "endif" */
431: if (percent) {
432: percent = 0;
433: if (level > 1) {
434: dst[-1] = '\n';
435: for (n = 0; n < level; n++)
436: *dst++ = '\t';
437: *dst++ = '%';
438: *dst++ = *src++;
439: *dst = '\0';
440: return src;
441: }
442: _nc_warning("%%; without %%?");
443: }
444: break;
445: default:
446: percent = 0;
447: break;
448: }
449: *dst++ = *src++;
450: }
451: *dst = '\0';
452: return src;
453: }
454:
455: int fmt_entry(TERMTYPE *tterm,
456: int (*pred)(int type, int idx),
457: bool suppress_untranslatable,
1.2 ! millert 458: bool infodump,
! 459: bool numbers)
1.1 millert 460: {
461: int i, j;
462: char buffer[MAX_TERMINFO_LENGTH];
463: int predval, len;
464: int num_bools = 0;
465: int num_values = 0;
466: int num_strings = 0;
467: bool outcount = 0;
468:
469: #define WRAP_CONCAT \
470: wrap_concat(buffer); \
471: outcount = TRUE
472:
473: len = 12; /* terminfo file-header */
474:
475: if (pred == 0) {
476: cur_type = tterm;
477: pred = dump_predicate;
478: }
479:
480: append_output(0);
481: append_output(tterm->term_names);
482: append_output(separator);
483: column = out_used;
484: force_wrap();
485:
486: for (j=0; j < BOOLCOUNT; j++) {
487: if (sortmode == S_NOSORT)
488: i = j;
489: else
490: i = bool_indirect[j];
491:
492: if (!version_filter(BOOLEAN, i))
493: continue;
494: else if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE)
495: && (OBSOLETE(bool_names[i]) && outform != F_LITERAL))
496: continue;
497:
498: predval = pred(BOOLEAN, i);
499: if (predval != FAIL) {
500: (void) strcpy(buffer, bool_names[i]);
501: if (predval <= 0)
502: (void) strcat(buffer, "@");
503: else if (i + 1 > num_bools)
504: num_bools = i + 1;
505: WRAP_CONCAT;
506: }
507: }
508:
509: if (column != INDENT)
510: force_wrap();
511:
512: for (j=0; j < NUMCOUNT; j++) {
513: if (sortmode == S_NOSORT)
514: i = j;
515: else
516: i = num_indirect[j];
517:
518: if (!version_filter(NUMBER, i))
519: continue;
520: else if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE)
521: && (OBSOLETE(num_names[i]) && outform != F_LITERAL))
522: continue;
523:
524: predval = pred(NUMBER, i);
525: if (predval != FAIL) {
526: if (tterm->Numbers[i] < 0) {
527: sprintf(buffer, "%s@", num_names[i]);
528: } else {
529: sprintf(buffer, "%s#%d", num_names[i], tterm->Numbers[i]);
530: if (i + 1 > num_values)
531: num_values = i + 1;
532: }
533: WRAP_CONCAT;
534: }
535: }
536:
537: if (column != INDENT)
538: force_wrap();
539:
540: len += num_bools
541: + num_values * 2
542: + strlen(tterm->term_names) + 1;
543: if (len & 1)
544: len++;
545:
546: repair_acsc(tterm);
547: for (j=0; j < STRCOUNT; j++) {
548: if (sortmode == S_NOSORT)
549: i = j;
550: else
551: i = str_indirect[j];
552:
553: if (!version_filter(STRING, i))
554: continue;
555: else if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE)
556: && (OBSOLETE(str_names[i]) && outform != F_LITERAL))
557: continue;
558:
559: /*
560: * Some older versions of vi want rmir/smir to be defined
561: * for ich/ich1 to work. If they're not defined, force
562: * them to be output as defined and empty.
563: */
564: if (outform==F_TERMCAP)
1.2 ! millert 565: {
1.1 millert 566: #undef CUR
567: #define CUR tterm->
568: if (insert_character || parm_ich)
569: {
570: if (&tterm->Strings[i] == &enter_insert_mode
571: && enter_insert_mode == ABSENT_STRING)
572: {
573: (void) strcpy(buffer, "im=");
574: goto catenate;
575: }
576:
577: if (&tterm->Strings[i] == &exit_insert_mode
578: && exit_insert_mode == ABSENT_STRING)
579: {
580: (void) strcpy(buffer, "ei=");
581: goto catenate;
582: }
583: }
584:
1.2 ! millert 585: if (init_3string != 0
! 586: && termcap_reset != 0
! 587: && !strcmp(init_3string, termcap_reset))
! 588: DISCARD(init_3string);
! 589:
! 590: if (reset_2string != 0
! 591: && termcap_reset != 0
! 592: && !strcmp(reset_2string, termcap_reset))
! 593: DISCARD(reset_2string);
! 594: }
! 595:
1.1 millert 596: predval = pred(STRING, i);
597: buffer[0] = '\0';
598: if (predval != FAIL) {
599: if (tterm->Strings[i] != ABSENT_STRING
600: && i + 1 > num_strings)
601: num_strings = i + 1;
602: if (!VALID_STRING(tterm->Strings[i]))
603: sprintf(buffer, "%s@", str_names[i]);
604: else if (outform == F_TERMCAP || outform == F_TCONVERR)
605: {
1.2 ! millert 606: char *srccap = _nc_tic_expand(tterm->Strings[i], FALSE, numbers);
1.1 millert 607: char *cv = _nc_infotocap(str_names[i], srccap, parametrized[i]);
608:
609: if (cv == 0)
610: {
611: if (outform == F_TCONVERR)
612: sprintf(buffer, "%s=!!! %s WILL NOT CONVERT !!!", str_names[i], srccap);
613: else if (suppress_untranslatable)
614: continue;
615: else
616: sprintf(buffer, "..%s=%s", str_names[i], srccap);
617: }
618: else
619: sprintf(buffer, "%s=%s", str_names[i], cv);
620: len += strlen(tterm->Strings[i]) + 1;
621: }
622: else
623: {
1.2 ! millert 624: char *src = _nc_tic_expand(tterm->Strings[i], outform==F_TERMINFO, numbers);
1.1 millert 625: sprintf(buffer, "%s=", str_names[i]);
626: if (pretty && outform==F_TERMINFO)
627: fmt_complex(buffer + strlen(buffer), src, 1);
628: else
629: strcat(buffer, src);
630: len += strlen(tterm->Strings[i]) + 1;
631: }
632:
633: catenate:
634: WRAP_CONCAT;
635: }
636: }
637: len += num_strings * 2;
638:
639: /*
640: * This piece of code should be an effective inverse of the functions
641: * postprocess_terminfo and postprocess_terminfo in parse_entry.c.
642: * Much more work should be done on this to support dumping termcaps.
643: */
644: if (tversion == V_HPUX)
645: {
646: if (memory_lock)
647: {
648: (void) sprintf(buffer, "meml=%s", memory_lock);
649: WRAP_CONCAT;
650: }
651: if (memory_unlock)
652: {
653: (void) sprintf(buffer, "memu=%s", memory_unlock);
654: WRAP_CONCAT;
655: }
656: }
657: else if (tversion == V_AIX)
658: {
659: if (VALID_STRING(acs_chars))
660: {
661: bool box_ok = TRUE;
662: const char *acstrans = "lqkxjmwuvtn";
663: const char *cp;
664: char *tp, *sp, boxchars[11];
665:
666: tp = boxchars;
667: for (cp = acstrans; *cp; cp++)
668: {
669: sp = strchr(acs_chars, *cp);
670: if (sp)
671: *tp++ = sp[1];
672: else
673: {
674: box_ok = FALSE;
675: break;
676: }
677: }
678: tp[0] = '\0';
679:
680: if (box_ok)
681: {
682: (void) strcpy(buffer, "box1=");
1.2 ! millert 683: (void) strcat(buffer, _nc_tic_expand(boxchars, outform==F_TERMINFO, numbers));
1.1 millert 684: WRAP_CONCAT;
685: }
686: }
687: }
688:
689: /*
690: * kludge: trim off trailer to avoid an extra blank line
691: * in infocmp -u output when there are no string differences
692: */
693: if (outcount)
694: {
695: j = out_used;
696: if (j >= 2
697: && outbuf[j-1] == '\t'
698: && outbuf[j-2] == '\n') {
699: out_used -= 2;
700: } else if (j >= 4
701: && outbuf[j-1] == ':'
702: && outbuf[j-2] == '\t'
703: && outbuf[j-3] == '\n'
704: && outbuf[j-4] == '\\') {
705: out_used -= 4;
706: }
707: outbuf[out_used] = '\0';
708: column = oldcol;
709: }
710:
711: #if 0
712: fprintf(stderr, "num_bools = %d\n", num_bools);
713: fprintf(stderr, "num_values = %d\n", num_values);
714: fprintf(stderr, "num_strings = %d\n", num_strings);
715: fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n",
716: tterm->term_names, len, out_used, outbuf);
717: #endif
718: /*
719: * Here's where we use infodump to trigger a more stringent length check
720: * for termcap-translation purposes.
721: * Return the length of the raw entry, without tc= expansions,
722: * It gives an idea of which entries are deadly to even *scan past*,
723: * as opposed to *use*.
724: */
725: return(infodump ? len : termcap_length(outbuf));
726: }
727:
1.2 ! millert 728: int dump_entry(TERMTYPE *tterm, bool limited, bool numbers, int (*pred)(int type, int idx))
1.1 millert 729: /* dump a single entry */
730: {
731: int len, critlen;
732: const char *legend;
733: bool infodump;
734:
735: if (outform==F_TERMCAP || outform==F_TCONVERR)
736: {
737: critlen = MAX_TERMCAP_LENGTH;
738: legend = "older termcap";
739: infodump = FALSE;
740: set_obsolete_termcaps(tterm);
741: }
742: else
743: {
744: critlen = MAX_TERMINFO_LENGTH;
745: legend = "terminfo";
746: infodump = TRUE;
747: }
748:
1.2 ! millert 749: if (((len = fmt_entry(tterm, pred, FALSE, infodump, numbers)) > critlen) && limited)
1.1 millert 750: {
751: (void) printf("# (untranslatable capabilities removed to fit entry within %d bytes)\n",
752: critlen);
1.2 ! millert 753: if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen)
1.1 millert 754: {
755: /*
756: * We pick on sgr because it's a nice long string capability that
757: * is really just an optimization hack.
758: */
759: char *oldsgr = set_attributes;
760: set_attributes = ABSENT_STRING;
761: (void) printf("# (sgr removed to fit entry within %d bytes)\n",
762: critlen);
1.2 ! millert 763: if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen)
1.1 millert 764: {
765: int oldversion = tversion;
766:
767: tversion = V_BSD;
768: (void) printf("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n",
769: critlen);
770:
1.2 ! millert 771: if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen)
1.1 millert 772: {
773: (void) fprintf(stderr,
774: "warning: %s entry is %d bytes long\n",
775: _nc_first_name(tterm->term_names),
776: len);
777: (void) printf(
778: "# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n",
779: len, legend);
780: }
781: tversion = oldversion;
782: }
783: set_attributes = oldsgr;
784: }
785: }
786:
787: (void) fputs(outbuf, stdout);
788: return len;
789: }
790:
791: int dump_uses(const char *name, bool infodump)
792: /* dump "use=" clauses in the appropriate format */
793: {
794: char buffer[MAX_TERMINFO_LENGTH];
795:
796: append_output(0);
797: (void)sprintf(buffer, "%s%s", infodump ? "use=" : "tc=", name);
798: wrap_concat(buffer);
799: (void) fputs(outbuf, stdout);
800: return out_used;
801: }
802:
803: void compare_entry(void (*hook)(int t, int i, const char *name))
804: /* compare two entries */
805: {
806: int i, j;
807:
808: (void) fputs(" comparing booleans.\n", stdout);
809: for (j=0; j < BOOLCOUNT; j++)
810: {
811: if (sortmode == S_NOSORT)
812: i = j;
813: else
814: i = bool_indirect[j];
815:
816: if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE)
817: && (OBSOLETE(bool_names[i]) && outform != F_LITERAL))
818: continue;
819:
820: (*hook)(BOOLEAN, i, bool_names[i]);
821: }
822:
823: (void) fputs(" comparing numbers.\n", stdout);
824: for (j=0; j < NUMCOUNT; j++)
825: {
826: if (sortmode == S_NOSORT)
827: i = j;
828: else
829: i = num_indirect[j];
830:
831: if ((outform==F_LITERAL || outform==F_TERMINFO || outform==F_VARIABLE)
832: && (OBSOLETE(num_names[i]) && outform != F_LITERAL))
833: continue;
834:
835: (*hook)(NUMBER, i, num_names[i]);
836: }
837:
838: (void) fputs(" comparing strings.\n", stdout);
839: for (j=0; j < STRCOUNT; j++)
840: {
841: if (sortmode == S_NOSORT)
842: i = j;
843: else
844: i = str_indirect[j];
845:
846: if ((outform==F_LITERAL || outform==F_TERMINFO || outform==F_VARIABLE)
847: && (OBSOLETE(str_names[i]) && outform != F_LITERAL))
848: continue;
849:
850: (*hook)(STRING, i, str_names[i]);
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: }