xref: /freebsd/contrib/ncurses/progs/tic.c (revision 0e3d540892016a47f6a68ec9ba2879d35ce5f7c2)
10e3d5408SPeter Wemm /****************************************************************************
20e3d5408SPeter Wemm  * Copyright (c) 1998,1999 Free Software Foundation, Inc.                   *
30e3d5408SPeter Wemm  *                                                                          *
40e3d5408SPeter Wemm  * Permission is hereby granted, free of charge, to any person obtaining a  *
50e3d5408SPeter Wemm  * copy of this software and associated documentation files (the            *
60e3d5408SPeter Wemm  * "Software"), to deal in the Software without restriction, including      *
70e3d5408SPeter Wemm  * without limitation the rights to use, copy, modify, merge, publish,      *
80e3d5408SPeter Wemm  * distribute, distribute with modifications, sublicense, and/or sell       *
90e3d5408SPeter Wemm  * copies of the Software, and to permit persons to whom the Software is    *
100e3d5408SPeter Wemm  * furnished to do so, subject to the following conditions:                 *
110e3d5408SPeter Wemm  *                                                                          *
120e3d5408SPeter Wemm  * The above copyright notice and this permission notice shall be included  *
130e3d5408SPeter Wemm  * in all copies or substantial portions of the Software.                   *
140e3d5408SPeter Wemm  *                                                                          *
150e3d5408SPeter Wemm  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
160e3d5408SPeter Wemm  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
170e3d5408SPeter Wemm  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
180e3d5408SPeter Wemm  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
190e3d5408SPeter Wemm  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
200e3d5408SPeter Wemm  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
210e3d5408SPeter Wemm  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
220e3d5408SPeter Wemm  *                                                                          *
230e3d5408SPeter Wemm  * Except as contained in this notice, the name(s) of the above copyright   *
240e3d5408SPeter Wemm  * holders shall not be used in advertising or otherwise to promote the     *
250e3d5408SPeter Wemm  * sale, use or other dealings in this Software without prior written       *
260e3d5408SPeter Wemm  * authorization.                                                           *
270e3d5408SPeter Wemm  ****************************************************************************/
280e3d5408SPeter Wemm 
290e3d5408SPeter Wemm /****************************************************************************
300e3d5408SPeter Wemm  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
310e3d5408SPeter Wemm  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
320e3d5408SPeter Wemm  ****************************************************************************/
330e3d5408SPeter Wemm 
340e3d5408SPeter Wemm /*
350e3d5408SPeter Wemm  *	tic.c --- Main program for terminfo compiler
360e3d5408SPeter Wemm  *			by Eric S. Raymond
370e3d5408SPeter Wemm  *
380e3d5408SPeter Wemm  */
390e3d5408SPeter Wemm 
400e3d5408SPeter Wemm #include <progs.priv.h>
410e3d5408SPeter Wemm 
420e3d5408SPeter Wemm #include <dump_entry.h>
430e3d5408SPeter Wemm #include <term_entry.h>
440e3d5408SPeter Wemm 
450e3d5408SPeter Wemm MODULE_ID("$Id: tic.c,v 1.51 1999/06/19 21:35:36 Philippe.De.Muyter Exp $")
460e3d5408SPeter Wemm 
470e3d5408SPeter Wemm const char *_nc_progname = "tic";
480e3d5408SPeter Wemm 
490e3d5408SPeter Wemm static	FILE	*log_fp;
500e3d5408SPeter Wemm static	FILE	*tmp_fp;
510e3d5408SPeter Wemm static	bool	showsummary = FALSE;
520e3d5408SPeter Wemm static	const char *to_remove;
530e3d5408SPeter Wemm 
540e3d5408SPeter Wemm static	void	(*save_check_termtype)(TERMTYPE *);
550e3d5408SPeter Wemm static	void	check_termtype(TERMTYPE *tt);
560e3d5408SPeter Wemm 
570e3d5408SPeter Wemm static	const	char usage_string[] = "[-h] [-v[n]] [-e names] [-CILNRTcfrswx1] source-file\n";
580e3d5408SPeter Wemm 
590e3d5408SPeter Wemm static void cleanup(void)
600e3d5408SPeter Wemm {
610e3d5408SPeter Wemm 	if (tmp_fp != 0)
620e3d5408SPeter Wemm 		fclose(tmp_fp);
630e3d5408SPeter Wemm 	if (to_remove != 0) {
640e3d5408SPeter Wemm #if HAVE_REMOVE
650e3d5408SPeter Wemm 		remove(to_remove);
660e3d5408SPeter Wemm #else
670e3d5408SPeter Wemm 		unlink(to_remove);
680e3d5408SPeter Wemm #endif
690e3d5408SPeter Wemm 	}
700e3d5408SPeter Wemm }
710e3d5408SPeter Wemm 
720e3d5408SPeter Wemm static void failed(const char *msg)
730e3d5408SPeter Wemm {
740e3d5408SPeter Wemm 	perror(msg);
750e3d5408SPeter Wemm 	cleanup();
760e3d5408SPeter Wemm 	exit(EXIT_FAILURE);
770e3d5408SPeter Wemm }
780e3d5408SPeter Wemm 
790e3d5408SPeter Wemm static void usage(void)
800e3d5408SPeter Wemm {
810e3d5408SPeter Wemm 	static const char *const tbl[] = {
820e3d5408SPeter Wemm 	"Options:",
830e3d5408SPeter Wemm 	"  -1         format translation output one capability per line",
840e3d5408SPeter Wemm 	"  -C         translate entries to termcap source form",
850e3d5408SPeter Wemm 	"  -I         translate entries to terminfo source form",
860e3d5408SPeter Wemm 	"  -L         translate entries to full terminfo source form",
870e3d5408SPeter Wemm 	"  -N         disable smart defaults for source translation",
880e3d5408SPeter Wemm 	"  -R         restrict translation to given terminfo/termcap version",
890e3d5408SPeter Wemm 	"  -T         remove size-restrictions on compiled description",
900e3d5408SPeter Wemm 	"  -c         check only, validate input without compiling or translating",
910e3d5408SPeter Wemm 	"  -f         format complex strings for readability",
920e3d5408SPeter Wemm 	"  -G         format %{number} to %'char'",
930e3d5408SPeter Wemm 	"  -g         format %'char' to %{number}",
940e3d5408SPeter Wemm 	"  -e<names>  translate/compile only entries named by comma-separated list",
950e3d5408SPeter Wemm 	"  -o<dir>    set output directory for compiled entry writes",
960e3d5408SPeter Wemm 	"  -r         force resolution of all use entries in source translation",
970e3d5408SPeter Wemm 	"  -s         print summary statistics",
980e3d5408SPeter Wemm 	"  -v[n]      set verbosity level",
990e3d5408SPeter Wemm 	"  -w[n]      set format width for translation output",
1000e3d5408SPeter Wemm #if NCURSES_XNAMES
1010e3d5408SPeter Wemm 	"  -x         treat unknown capabilities as user-defined",
1020e3d5408SPeter Wemm #endif
1030e3d5408SPeter Wemm 	"",
1040e3d5408SPeter Wemm 	"Parameters:",
1050e3d5408SPeter Wemm 	"  <file>     file to translate or compile"
1060e3d5408SPeter Wemm 	};
1070e3d5408SPeter Wemm 	size_t j;
1080e3d5408SPeter Wemm 
1090e3d5408SPeter Wemm 	printf("Usage: %s %s\n", _nc_progname, usage_string);
1100e3d5408SPeter Wemm 	for (j = 0; j < sizeof(tbl)/sizeof(tbl[0]); j++)
1110e3d5408SPeter Wemm 		puts(tbl[j]);
1120e3d5408SPeter Wemm 	exit(EXIT_FAILURE);
1130e3d5408SPeter Wemm }
1140e3d5408SPeter Wemm 
1150e3d5408SPeter Wemm #define L_BRACE '{'
1160e3d5408SPeter Wemm #define R_BRACE '}'
1170e3d5408SPeter Wemm #define S_QUOTE '\'';
1180e3d5408SPeter Wemm 
1190e3d5408SPeter Wemm static void write_it(ENTRY *ep)
1200e3d5408SPeter Wemm {
1210e3d5408SPeter Wemm 	unsigned n;
1220e3d5408SPeter Wemm 	int ch;
1230e3d5408SPeter Wemm 	char *s, *d, *t;
1240e3d5408SPeter Wemm 	char result[MAX_ENTRY_SIZE];
1250e3d5408SPeter Wemm 
1260e3d5408SPeter Wemm 	/*
1270e3d5408SPeter Wemm 	 * Look for strings that contain %{number}, convert them to %'char',
1280e3d5408SPeter Wemm 	 * which is shorter and runs a little faster.
1290e3d5408SPeter Wemm 	 */
1300e3d5408SPeter Wemm 	for (n = 0; n < STRCOUNT; n++) {
1310e3d5408SPeter Wemm 		s = ep->tterm.Strings[n];
1320e3d5408SPeter Wemm 		if (VALID_STRING(s)
1330e3d5408SPeter Wemm 		 && strchr(s, L_BRACE) != 0) {
1340e3d5408SPeter Wemm 			d = result;
1350e3d5408SPeter Wemm 			t = s;
1360e3d5408SPeter Wemm 			while ((ch = *t++) != 0) {
1370e3d5408SPeter Wemm 				*d++ = ch;
1380e3d5408SPeter Wemm 				if (ch == '\\') {
1390e3d5408SPeter Wemm 					*d++ = *t++;
1400e3d5408SPeter Wemm 				} else if ((ch == '%')
1410e3d5408SPeter Wemm 				 && (*t == L_BRACE)) {
1420e3d5408SPeter Wemm 					char *v = 0;
1430e3d5408SPeter Wemm 					long value = strtol(t+1, &v, 0);
1440e3d5408SPeter Wemm 					if (v != 0
1450e3d5408SPeter Wemm 					 && *v == R_BRACE
1460e3d5408SPeter Wemm 					 && value > 0
1470e3d5408SPeter Wemm 					 && value != '\\'	/* FIXME */
1480e3d5408SPeter Wemm 					 && value < 127
1490e3d5408SPeter Wemm 					 && isprint((int)value)) {
1500e3d5408SPeter Wemm 						*d++ = S_QUOTE;
1510e3d5408SPeter Wemm 						*d++ = (int)value;
1520e3d5408SPeter Wemm 						*d++ = S_QUOTE;
1530e3d5408SPeter Wemm 						t = (v + 1);
1540e3d5408SPeter Wemm 					}
1550e3d5408SPeter Wemm 				}
1560e3d5408SPeter Wemm 			}
1570e3d5408SPeter Wemm 			*d = 0;
1580e3d5408SPeter Wemm 			if (strlen(result) < strlen(s))
1590e3d5408SPeter Wemm 				strcpy(s, result);
1600e3d5408SPeter Wemm 		}
1610e3d5408SPeter Wemm 	}
1620e3d5408SPeter Wemm 
1630e3d5408SPeter Wemm 	_nc_set_type(_nc_first_name(ep->tterm.term_names));
1640e3d5408SPeter Wemm 	_nc_curr_line = ep->startline;
1650e3d5408SPeter Wemm 	_nc_write_entry(&ep->tterm);
1660e3d5408SPeter Wemm }
1670e3d5408SPeter Wemm 
1680e3d5408SPeter Wemm static bool immedhook(ENTRY *ep GCC_UNUSED)
1690e3d5408SPeter Wemm /* write out entries with no use capabilities immediately to save storage */
1700e3d5408SPeter Wemm {
1710e3d5408SPeter Wemm #ifndef HAVE_BIG_CORE
1720e3d5408SPeter Wemm     /*
1730e3d5408SPeter Wemm      * This is strictly a core-economy kluge.  The really clean way to handle
1740e3d5408SPeter Wemm      * compilation is to slurp the whole file into core and then do all the
1750e3d5408SPeter Wemm      * name-collision checks and entry writes in one swell foop.  But the
1760e3d5408SPeter Wemm      * terminfo master file is large enough that some core-poor systems swap
1770e3d5408SPeter Wemm      * like crazy when you compile it this way...there have been reports of
1780e3d5408SPeter Wemm      * this process taking *three hours*, rather than the twenty seconds or
1790e3d5408SPeter Wemm      * less typical on my development box.
1800e3d5408SPeter Wemm      *
1810e3d5408SPeter Wemm      * So.  This hook *immediately* writes out the referenced entry if it
1820e3d5408SPeter Wemm      * has no use capabilities.  The compiler main loop refrains from
1830e3d5408SPeter Wemm      * adding the entry to the in-core list when this hook fires.  If some
1840e3d5408SPeter Wemm      * other entry later needs to reference an entry that got written
1850e3d5408SPeter Wemm      * immediately, that's OK; the resolution code will fetch it off disk
1860e3d5408SPeter Wemm      * when it can't find it in core.
1870e3d5408SPeter Wemm      *
1880e3d5408SPeter Wemm      * Name collisions will still be detected, just not as cleanly.  The
1890e3d5408SPeter Wemm      * write_entry() code complains before overwriting an entry that
1900e3d5408SPeter Wemm      * postdates the time of tic's first call to write_entry().  Thus
1910e3d5408SPeter Wemm      * it will complain about overwriting entries newly made during the
1920e3d5408SPeter Wemm      * tic run, but not about overwriting ones that predate it.
1930e3d5408SPeter Wemm      *
1940e3d5408SPeter Wemm      * The reason this is a hook, and not in line with the rest of the
1950e3d5408SPeter Wemm      * compiler code, is that the support for termcap fallback cannot assume
1960e3d5408SPeter Wemm      * it has anywhere to spool out these entries!
1970e3d5408SPeter Wemm      *
1980e3d5408SPeter Wemm      * The _nc_set_type() call here requires a compensating one in
1990e3d5408SPeter Wemm      * _nc_parse_entry().
2000e3d5408SPeter Wemm      *
2010e3d5408SPeter Wemm      * If you define HAVE_BIG_CORE, you'll disable this kluge.  This will
2020e3d5408SPeter Wemm      * make tic a bit faster (because the resolution code won't have to do
2030e3d5408SPeter Wemm      * disk I/O nearly as often).
2040e3d5408SPeter Wemm      */
2050e3d5408SPeter Wemm     if (ep->nuses == 0)
2060e3d5408SPeter Wemm     {
2070e3d5408SPeter Wemm 	int	oldline = _nc_curr_line;
2080e3d5408SPeter Wemm 
2090e3d5408SPeter Wemm 	write_it(ep);
2100e3d5408SPeter Wemm 	_nc_curr_line = oldline;
2110e3d5408SPeter Wemm 	free(ep->tterm.str_table);
2120e3d5408SPeter Wemm 	return(TRUE);
2130e3d5408SPeter Wemm     }
2140e3d5408SPeter Wemm #endif /* HAVE_BIG_CORE */
2150e3d5408SPeter Wemm     return(FALSE);
2160e3d5408SPeter Wemm }
2170e3d5408SPeter Wemm 
2180e3d5408SPeter Wemm static void put_translate(int c)
2190e3d5408SPeter Wemm /* emit a comment char, translating terminfo names to termcap names */
2200e3d5408SPeter Wemm {
2210e3d5408SPeter Wemm     static bool in_name = FALSE;
2220e3d5408SPeter Wemm     static char namebuf[132], suffix[132], *sp;
2230e3d5408SPeter Wemm 
2240e3d5408SPeter Wemm     if (!in_name)
2250e3d5408SPeter Wemm     {
2260e3d5408SPeter Wemm 	if (c == '<')
2270e3d5408SPeter Wemm 	{
2280e3d5408SPeter Wemm 	    in_name = TRUE;
2290e3d5408SPeter Wemm 	    sp = namebuf;
2300e3d5408SPeter Wemm 	}
2310e3d5408SPeter Wemm 	else
2320e3d5408SPeter Wemm 	    putchar(c);
2330e3d5408SPeter Wemm     }
2340e3d5408SPeter Wemm     else if (c == '\n' || c == '@')
2350e3d5408SPeter Wemm     {
2360e3d5408SPeter Wemm 	*sp++ = '\0';
2370e3d5408SPeter Wemm 	(void) putchar('<');
2380e3d5408SPeter Wemm 	(void) fputs(namebuf, stdout);
2390e3d5408SPeter Wemm 	putchar(c);
2400e3d5408SPeter Wemm 	in_name = FALSE;
2410e3d5408SPeter Wemm     }
2420e3d5408SPeter Wemm     else if (c != '>')
2430e3d5408SPeter Wemm 	*sp++ = c;
2440e3d5408SPeter Wemm     else		/* ah! candidate name! */
2450e3d5408SPeter Wemm     {
2460e3d5408SPeter Wemm 	char	*up;
2470e3d5408SPeter Wemm 	NCURSES_CONST char *tp;
2480e3d5408SPeter Wemm 
2490e3d5408SPeter Wemm 	*sp++ = '\0';
2500e3d5408SPeter Wemm 	in_name = FALSE;
2510e3d5408SPeter Wemm 
2520e3d5408SPeter Wemm 	suffix[0] = '\0';
2530e3d5408SPeter Wemm 	if ((up = strchr(namebuf, '#')) != 0
2540e3d5408SPeter Wemm 	 || (up = strchr(namebuf, '=')) != 0
2550e3d5408SPeter Wemm 	 || ((up = strchr(namebuf, '@')) != 0 && up[1] == '>'))
2560e3d5408SPeter Wemm 	{
2570e3d5408SPeter Wemm 	    (void) strcpy(suffix, up);
2580e3d5408SPeter Wemm 	    *up = '\0';
2590e3d5408SPeter Wemm 	}
2600e3d5408SPeter Wemm 
2610e3d5408SPeter Wemm 	if ((tp = nametrans(namebuf)) != 0)
2620e3d5408SPeter Wemm 	{
2630e3d5408SPeter Wemm 	    (void) putchar(':');
2640e3d5408SPeter Wemm 	    (void) fputs(tp, stdout);
2650e3d5408SPeter Wemm 	    (void) fputs(suffix, stdout);
2660e3d5408SPeter Wemm 	    (void) putchar(':');
2670e3d5408SPeter Wemm 	}
2680e3d5408SPeter Wemm 	else
2690e3d5408SPeter Wemm 	{
2700e3d5408SPeter Wemm 	    /* couldn't find a translation, just dump the name */
2710e3d5408SPeter Wemm 	    (void) putchar('<');
2720e3d5408SPeter Wemm 	    (void) fputs(namebuf, stdout);
2730e3d5408SPeter Wemm 	    (void) fputs(suffix, stdout);
2740e3d5408SPeter Wemm 	    (void) putchar('>');
2750e3d5408SPeter Wemm 	}
2760e3d5408SPeter Wemm 
2770e3d5408SPeter Wemm     }
2780e3d5408SPeter Wemm }
2790e3d5408SPeter Wemm 
2800e3d5408SPeter Wemm /* Returns a string, stripped of leading/trailing whitespace */
2810e3d5408SPeter Wemm static char *stripped(char *src)
2820e3d5408SPeter Wemm {
2830e3d5408SPeter Wemm 	while (isspace(*src))
2840e3d5408SPeter Wemm 		src++;
2850e3d5408SPeter Wemm 	if (*src != '\0') {
2860e3d5408SPeter Wemm 		char *dst = strcpy(malloc(strlen(src)+1), src);
2870e3d5408SPeter Wemm 		size_t len = strlen(dst);
2880e3d5408SPeter Wemm 		while (--len != 0 && isspace(dst[len]))
2890e3d5408SPeter Wemm 			dst[len] = '\0';
2900e3d5408SPeter Wemm 		return dst;
2910e3d5408SPeter Wemm 	}
2920e3d5408SPeter Wemm 	return 0;
2930e3d5408SPeter Wemm }
2940e3d5408SPeter Wemm 
2950e3d5408SPeter Wemm /* Parse the "-e" option-value into a list of names */
2960e3d5408SPeter Wemm static const char **make_namelist(char *src)
2970e3d5408SPeter Wemm {
2980e3d5408SPeter Wemm 	const char **dst = 0;
2990e3d5408SPeter Wemm 
3000e3d5408SPeter Wemm 	char *s, *base;
3010e3d5408SPeter Wemm 	unsigned pass, n, nn;
3020e3d5408SPeter Wemm 	char buffer[BUFSIZ];
3030e3d5408SPeter Wemm 
3040e3d5408SPeter Wemm 	if (src == 0) {
3050e3d5408SPeter Wemm 		/* EMPTY */;
3060e3d5408SPeter Wemm 	} else if (strchr(src, '/') != 0) {	/* a filename */
3070e3d5408SPeter Wemm 		FILE *fp = fopen(src, "r");
3080e3d5408SPeter Wemm 		if (fp == 0)
3090e3d5408SPeter Wemm 			failed(src);
3100e3d5408SPeter Wemm 
3110e3d5408SPeter Wemm 		for (pass = 1; pass <= 2; pass++) {
3120e3d5408SPeter Wemm 			nn = 0;
3130e3d5408SPeter Wemm 			while (fgets(buffer, sizeof(buffer), fp) != 0) {
3140e3d5408SPeter Wemm 				if ((s = stripped(buffer)) != 0) {
3150e3d5408SPeter Wemm 					if (dst != 0)
3160e3d5408SPeter Wemm 						dst[nn] = s;
3170e3d5408SPeter Wemm 					nn++;
3180e3d5408SPeter Wemm 				}
3190e3d5408SPeter Wemm 			}
3200e3d5408SPeter Wemm 			if (pass == 1) {
3210e3d5408SPeter Wemm 				dst = (const char **)calloc(nn+1, sizeof(*dst));
3220e3d5408SPeter Wemm 				rewind(fp);
3230e3d5408SPeter Wemm 			}
3240e3d5408SPeter Wemm 		}
3250e3d5408SPeter Wemm 		fclose(fp);
3260e3d5408SPeter Wemm 	} else {			/* literal list of names */
3270e3d5408SPeter Wemm 		for (pass = 1; pass <= 2; pass++) {
3280e3d5408SPeter Wemm 			for (n = nn = 0, base = src; ; n++) {
3290e3d5408SPeter Wemm 				int mark = src[n];
3300e3d5408SPeter Wemm 				if (mark == ',' || mark == '\0') {
3310e3d5408SPeter Wemm 					if (pass == 1) {
3320e3d5408SPeter Wemm 						nn++;
3330e3d5408SPeter Wemm 					} else {
3340e3d5408SPeter Wemm 						src[n] = '\0';
3350e3d5408SPeter Wemm 						if ((s = stripped(base)) != 0)
3360e3d5408SPeter Wemm 							dst[nn++] = s;
3370e3d5408SPeter Wemm 						base = &src[n+1];
3380e3d5408SPeter Wemm 					}
3390e3d5408SPeter Wemm 				}
3400e3d5408SPeter Wemm 				if (mark == '\0')
3410e3d5408SPeter Wemm 					break;
3420e3d5408SPeter Wemm 			}
3430e3d5408SPeter Wemm 			if (pass == 1)
3440e3d5408SPeter Wemm 				dst = (const char **)calloc(nn+1, sizeof(*dst));
3450e3d5408SPeter Wemm 		}
3460e3d5408SPeter Wemm 	}
3470e3d5408SPeter Wemm 	if (showsummary) {
3480e3d5408SPeter Wemm 		fprintf(log_fp, "Entries that will be compiled:\n");
3490e3d5408SPeter Wemm 		for (n = 0; dst[n] != 0; n++)
3500e3d5408SPeter Wemm 			fprintf(log_fp, "%d:%s\n", n+1, dst[n]);
3510e3d5408SPeter Wemm 	}
3520e3d5408SPeter Wemm 	return dst;
3530e3d5408SPeter Wemm }
3540e3d5408SPeter Wemm 
3550e3d5408SPeter Wemm static bool matches(const char **needle, const char *haystack)
3560e3d5408SPeter Wemm /* does entry in needle list match |-separated field in haystack? */
3570e3d5408SPeter Wemm {
3580e3d5408SPeter Wemm 	bool code = FALSE;
3590e3d5408SPeter Wemm 	size_t n;
3600e3d5408SPeter Wemm 
3610e3d5408SPeter Wemm 	if (needle != 0)
3620e3d5408SPeter Wemm 	{
3630e3d5408SPeter Wemm 		for (n = 0; needle[n] != 0; n++)
3640e3d5408SPeter Wemm 		{
3650e3d5408SPeter Wemm 			if (_nc_name_match(haystack, needle[n], "|"))
3660e3d5408SPeter Wemm 			{
3670e3d5408SPeter Wemm 				code = TRUE;
3680e3d5408SPeter Wemm 				break;
3690e3d5408SPeter Wemm 			}
3700e3d5408SPeter Wemm 		}
3710e3d5408SPeter Wemm 	}
3720e3d5408SPeter Wemm 	else
3730e3d5408SPeter Wemm 		code = TRUE;
3740e3d5408SPeter Wemm 	return(code);
3750e3d5408SPeter Wemm }
3760e3d5408SPeter Wemm 
3770e3d5408SPeter Wemm int main (int argc, char *argv[])
3780e3d5408SPeter Wemm {
3790e3d5408SPeter Wemm char	my_tmpname[PATH_MAX];
3800e3d5408SPeter Wemm int	v_opt = -1, debug_level;
3810e3d5408SPeter Wemm int	smart_defaults = TRUE;
3820e3d5408SPeter Wemm char    *termcap;
3830e3d5408SPeter Wemm ENTRY	*qp;
3840e3d5408SPeter Wemm 
3850e3d5408SPeter Wemm int	this_opt, last_opt = '?';
3860e3d5408SPeter Wemm 
3870e3d5408SPeter Wemm int	outform = F_TERMINFO;	/* output format */
3880e3d5408SPeter Wemm int	sortmode = S_TERMINFO;	/* sort_mode */
3890e3d5408SPeter Wemm 
3900e3d5408SPeter Wemm int	width = 60;
3910e3d5408SPeter Wemm bool	formatted = FALSE;	/* reformat complex strings? */
3920e3d5408SPeter Wemm int	numbers = 0;		/* format "%'char'" to/from "%{number}" */
3930e3d5408SPeter Wemm bool	infodump = FALSE;	/* running as captoinfo? */
3940e3d5408SPeter Wemm bool	capdump = FALSE;	/* running as infotocap? */
3950e3d5408SPeter Wemm bool	forceresolve = FALSE;	/* force resolution */
3960e3d5408SPeter Wemm bool	limited = TRUE;
3970e3d5408SPeter Wemm char	*tversion = (char *)NULL;
3980e3d5408SPeter Wemm const	char	*source_file = "terminfo";
3990e3d5408SPeter Wemm const	char	**namelst = 0;
4000e3d5408SPeter Wemm char	*outdir = (char *)NULL;
4010e3d5408SPeter Wemm bool	check_only = FALSE;
4020e3d5408SPeter Wemm 
4030e3d5408SPeter Wemm 	log_fp = stderr;
4040e3d5408SPeter Wemm 
4050e3d5408SPeter Wemm 	if ((_nc_progname = strrchr(argv[0], '/')) == NULL)
4060e3d5408SPeter Wemm 		_nc_progname = argv[0];
4070e3d5408SPeter Wemm 	else
4080e3d5408SPeter Wemm 		_nc_progname++;
4090e3d5408SPeter Wemm 
4100e3d5408SPeter Wemm 	infodump = (strcmp(_nc_progname, "captoinfo") == 0);
4110e3d5408SPeter Wemm 	capdump = (strcmp(_nc_progname, "infotocap") == 0);
4120e3d5408SPeter Wemm #if NCURSES_XNAMES
4130e3d5408SPeter Wemm 	use_extended_names(FALSE);
4140e3d5408SPeter Wemm #endif
4150e3d5408SPeter Wemm 
4160e3d5408SPeter Wemm 	/*
4170e3d5408SPeter Wemm 	 * Processing arguments is a little complicated, since someone made a
4180e3d5408SPeter Wemm 	 * design decision to allow the numeric values for -w, -v options to
4190e3d5408SPeter Wemm 	 * be optional.
4200e3d5408SPeter Wemm 	 */
4210e3d5408SPeter Wemm 	while ((this_opt = getopt(argc, argv, "0123456789CILNR:TVce:fGgo:rsvwx")) != EOF) {
4220e3d5408SPeter Wemm 		if (isdigit(this_opt)) {
4230e3d5408SPeter Wemm 			switch (last_opt) {
4240e3d5408SPeter Wemm 			case 'v':
4250e3d5408SPeter Wemm 				v_opt = (v_opt * 10) + (this_opt - '0');
4260e3d5408SPeter Wemm 				break;
4270e3d5408SPeter Wemm 			case 'w':
4280e3d5408SPeter Wemm 				width = (width * 10) + (this_opt - '0');
4290e3d5408SPeter Wemm 				break;
4300e3d5408SPeter Wemm 			default:
4310e3d5408SPeter Wemm 				if (this_opt != '1')
4320e3d5408SPeter Wemm 					usage();
4330e3d5408SPeter Wemm 				last_opt = this_opt;
4340e3d5408SPeter Wemm 				width = 0;
4350e3d5408SPeter Wemm 			}
4360e3d5408SPeter Wemm 			continue;
4370e3d5408SPeter Wemm 		}
4380e3d5408SPeter Wemm 		switch (this_opt) {
4390e3d5408SPeter Wemm 		case 'C':
4400e3d5408SPeter Wemm 			capdump  = TRUE;
4410e3d5408SPeter Wemm 			outform  = F_TERMCAP;
4420e3d5408SPeter Wemm 			sortmode = S_TERMCAP;
4430e3d5408SPeter Wemm 			break;
4440e3d5408SPeter Wemm 		case 'I':
4450e3d5408SPeter Wemm 			infodump = TRUE;
4460e3d5408SPeter Wemm 			outform  = F_TERMINFO;
4470e3d5408SPeter Wemm 			sortmode = S_TERMINFO;
4480e3d5408SPeter Wemm 			break;
4490e3d5408SPeter Wemm 		case 'L':
4500e3d5408SPeter Wemm 			infodump = TRUE;
4510e3d5408SPeter Wemm 			outform  = F_VARIABLE;
4520e3d5408SPeter Wemm 			sortmode = S_VARIABLE;
4530e3d5408SPeter Wemm 			break;
4540e3d5408SPeter Wemm 		case 'N':
4550e3d5408SPeter Wemm 			smart_defaults = FALSE;
4560e3d5408SPeter Wemm 			break;
4570e3d5408SPeter Wemm 		case 'R':
4580e3d5408SPeter Wemm 			tversion = optarg;
4590e3d5408SPeter Wemm 			break;
4600e3d5408SPeter Wemm 		case 'T':
4610e3d5408SPeter Wemm 			limited = FALSE;
4620e3d5408SPeter Wemm 			break;
4630e3d5408SPeter Wemm 		case 'V':
4640e3d5408SPeter Wemm 			puts(NCURSES_VERSION);
4650e3d5408SPeter Wemm 			return EXIT_SUCCESS;
4660e3d5408SPeter Wemm 		case 'c':
4670e3d5408SPeter Wemm 			check_only = TRUE;
4680e3d5408SPeter Wemm 			break;
4690e3d5408SPeter Wemm 		case 'e':
4700e3d5408SPeter Wemm 			namelst = make_namelist(optarg);
4710e3d5408SPeter Wemm 			break;
4720e3d5408SPeter Wemm 		case 'f':
4730e3d5408SPeter Wemm 			formatted = TRUE;
4740e3d5408SPeter Wemm 			break;
4750e3d5408SPeter Wemm 		case 'G':
4760e3d5408SPeter Wemm 			numbers = 1;
4770e3d5408SPeter Wemm 			break;
4780e3d5408SPeter Wemm 		case 'g':
4790e3d5408SPeter Wemm 			numbers = -1;
4800e3d5408SPeter Wemm 			break;
4810e3d5408SPeter Wemm 		case 'o':
4820e3d5408SPeter Wemm 			outdir = optarg;
4830e3d5408SPeter Wemm 			break;
4840e3d5408SPeter Wemm 		case 'r':
4850e3d5408SPeter Wemm 			forceresolve = TRUE;
4860e3d5408SPeter Wemm 			break;
4870e3d5408SPeter Wemm 		case 's':
4880e3d5408SPeter Wemm 			showsummary = TRUE;
4890e3d5408SPeter Wemm 			break;
4900e3d5408SPeter Wemm 		case 'v':
4910e3d5408SPeter Wemm 			v_opt = 0;
4920e3d5408SPeter Wemm 			break;
4930e3d5408SPeter Wemm 		case 'w':
4940e3d5408SPeter Wemm 			width = 0;
4950e3d5408SPeter Wemm 			break;
4960e3d5408SPeter Wemm #if NCURSES_XNAMES
4970e3d5408SPeter Wemm 		case 'x':
4980e3d5408SPeter Wemm 			use_extended_names(TRUE);
4990e3d5408SPeter Wemm 			break;
5000e3d5408SPeter Wemm #endif
5010e3d5408SPeter Wemm 		default:
5020e3d5408SPeter Wemm 			usage();
5030e3d5408SPeter Wemm 		}
5040e3d5408SPeter Wemm 		last_opt = this_opt;
5050e3d5408SPeter Wemm 	}
5060e3d5408SPeter Wemm 
5070e3d5408SPeter Wemm 	debug_level = (v_opt > 0) ? v_opt : (v_opt == 0);
5080e3d5408SPeter Wemm 	_nc_tracing = (1 << debug_level) - 1;
5090e3d5408SPeter Wemm 
5100e3d5408SPeter Wemm 	if (_nc_tracing)
5110e3d5408SPeter Wemm 	{
5120e3d5408SPeter Wemm 		save_check_termtype = _nc_check_termtype;
5130e3d5408SPeter Wemm 		_nc_check_termtype = check_termtype;
5140e3d5408SPeter Wemm 	}
5150e3d5408SPeter Wemm 
5160e3d5408SPeter Wemm #ifndef HAVE_BIG_CORE
5170e3d5408SPeter Wemm 	/*
5180e3d5408SPeter Wemm 	 * Aaargh! immedhook seriously hoses us!
5190e3d5408SPeter Wemm 	 *
5200e3d5408SPeter Wemm 	 * One problem with immedhook is it means we can't do -e.  Problem
5210e3d5408SPeter Wemm 	 * is that we can't guarantee that for each terminal listed, all the
5220e3d5408SPeter Wemm 	 * terminals it depends on will have been kept in core for reference
5230e3d5408SPeter Wemm 	 * resolution -- in fact it's certain the primitive types at the end
5240e3d5408SPeter Wemm 	 * of reference chains *won't* be in core unless they were explicitly
5250e3d5408SPeter Wemm 	 * in the select list themselves.
5260e3d5408SPeter Wemm 	 */
5270e3d5408SPeter Wemm 	if (namelst && (!infodump && !capdump))
5280e3d5408SPeter Wemm 	{
5290e3d5408SPeter Wemm 	    (void) fprintf(stderr,
5300e3d5408SPeter Wemm 			   "Sorry, -e can't be used without -I or -C\n");
5310e3d5408SPeter Wemm 	    cleanup();
5320e3d5408SPeter Wemm 	    return EXIT_FAILURE;
5330e3d5408SPeter Wemm 	}
5340e3d5408SPeter Wemm #endif /* HAVE_BIG_CORE */
5350e3d5408SPeter Wemm 
5360e3d5408SPeter Wemm 	if (optind < argc) {
5370e3d5408SPeter Wemm 		source_file = argv[optind++];
5380e3d5408SPeter Wemm 		if (optind < argc) {
5390e3d5408SPeter Wemm 			fprintf (stderr,
5400e3d5408SPeter Wemm 				"%s: Too many file names.  Usage:\n\t%s %s",
5410e3d5408SPeter Wemm 				_nc_progname,
5420e3d5408SPeter Wemm 				_nc_progname,
5430e3d5408SPeter Wemm 				usage_string);
5440e3d5408SPeter Wemm 			return EXIT_FAILURE;
5450e3d5408SPeter Wemm 		}
5460e3d5408SPeter Wemm 	} else {
5470e3d5408SPeter Wemm 		if (infodump == TRUE) {
5480e3d5408SPeter Wemm 			/* captoinfo's no-argument case */
5490e3d5408SPeter Wemm 			source_file = "/etc/termcap";
5500e3d5408SPeter Wemm 			if ((termcap = getenv("TERMCAP")) != 0
5510e3d5408SPeter Wemm 			 && (namelst = make_namelist(getenv("TERM"))) != 0) {
5520e3d5408SPeter Wemm 				if (access(termcap, F_OK) == 0) {
5530e3d5408SPeter Wemm 					/* file exists */
5540e3d5408SPeter Wemm 					source_file = termcap;
5550e3d5408SPeter Wemm 				} else
5560e3d5408SPeter Wemm 				if ((source_file = tmpnam(my_tmpname)) != 0
5570e3d5408SPeter Wemm 				 && (tmp_fp = fopen(source_file, "w")) != 0) {
5580e3d5408SPeter Wemm 					fprintf(tmp_fp, "%s\n", termcap);
5590e3d5408SPeter Wemm 					fclose(tmp_fp);
5600e3d5408SPeter Wemm 					tmp_fp = fopen(source_file, "r");
5610e3d5408SPeter Wemm 					to_remove = source_file;
5620e3d5408SPeter Wemm 				} else {
5630e3d5408SPeter Wemm 					failed("tmpnam");
5640e3d5408SPeter Wemm 				}
5650e3d5408SPeter Wemm 			}
5660e3d5408SPeter Wemm 		} else {
5670e3d5408SPeter Wemm 		/* tic */
5680e3d5408SPeter Wemm 			fprintf (stderr,
5690e3d5408SPeter Wemm 				"%s: File name needed.  Usage:\n\t%s %s",
5700e3d5408SPeter Wemm 				_nc_progname,
5710e3d5408SPeter Wemm 				_nc_progname,
5720e3d5408SPeter Wemm 				usage_string);
5730e3d5408SPeter Wemm 			cleanup();
5740e3d5408SPeter Wemm 			return EXIT_FAILURE;
5750e3d5408SPeter Wemm 		}
5760e3d5408SPeter Wemm 	}
5770e3d5408SPeter Wemm 
5780e3d5408SPeter Wemm 	if (tmp_fp == 0
5790e3d5408SPeter Wemm 	 && (tmp_fp = fopen(source_file, "r")) == 0) {
5800e3d5408SPeter Wemm 		fprintf (stderr, "%s: Can't open %s\n", _nc_progname, source_file);
5810e3d5408SPeter Wemm 		return EXIT_FAILURE;
5820e3d5408SPeter Wemm 	}
5830e3d5408SPeter Wemm 
5840e3d5408SPeter Wemm 	if (infodump)
5850e3d5408SPeter Wemm 		dump_init(tversion,
5860e3d5408SPeter Wemm 			  smart_defaults
5870e3d5408SPeter Wemm 				? outform
5880e3d5408SPeter Wemm 				: F_LITERAL,
5890e3d5408SPeter Wemm 			  sortmode, width, debug_level, formatted);
5900e3d5408SPeter Wemm 	else if (capdump)
5910e3d5408SPeter Wemm 		dump_init(tversion,
5920e3d5408SPeter Wemm 			  outform,
5930e3d5408SPeter Wemm 			  sortmode, width, debug_level, FALSE);
5940e3d5408SPeter Wemm 
5950e3d5408SPeter Wemm 	/* parse entries out of the source file */
5960e3d5408SPeter Wemm 	_nc_set_source(source_file);
5970e3d5408SPeter Wemm #ifndef HAVE_BIG_CORE
5980e3d5408SPeter Wemm 	if (!(check_only || infodump || capdump))
5990e3d5408SPeter Wemm 	    _nc_set_writedir(outdir);
6000e3d5408SPeter Wemm #endif /* HAVE_BIG_CORE */
6010e3d5408SPeter Wemm 	_nc_read_entry_source(tmp_fp, (char *)NULL,
6020e3d5408SPeter Wemm 			      !smart_defaults, FALSE,
6030e3d5408SPeter Wemm 			      (check_only || infodump || capdump) ? NULLHOOK : immedhook);
6040e3d5408SPeter Wemm 
6050e3d5408SPeter Wemm 	/* do use resolution */
6060e3d5408SPeter Wemm 	if (check_only || (!infodump && !capdump) || forceresolve) {
6070e3d5408SPeter Wemm 	    if (!_nc_resolve_uses() && !check_only) {
6080e3d5408SPeter Wemm 		cleanup();
6090e3d5408SPeter Wemm 		return EXIT_FAILURE;
6100e3d5408SPeter Wemm 	    }
6110e3d5408SPeter Wemm 	}
6120e3d5408SPeter Wemm 
6130e3d5408SPeter Wemm 	/* length check */
6140e3d5408SPeter Wemm 	if (check_only && (capdump || infodump))
6150e3d5408SPeter Wemm 	{
6160e3d5408SPeter Wemm 	    for_entry_list(qp)
6170e3d5408SPeter Wemm 	    {
6180e3d5408SPeter Wemm 		if (matches(namelst, qp->tterm.term_names))
6190e3d5408SPeter Wemm 		{
6200e3d5408SPeter Wemm 		    int	len = fmt_entry(&qp->tterm, NULL, TRUE, infodump, numbers);
6210e3d5408SPeter Wemm 
6220e3d5408SPeter Wemm 		    if (len>(infodump?MAX_TERMINFO_LENGTH:MAX_TERMCAP_LENGTH))
6230e3d5408SPeter Wemm 			    (void) fprintf(stderr,
6240e3d5408SPeter Wemm 			   "warning: resolved %s entry is %d bytes long\n",
6250e3d5408SPeter Wemm 			   _nc_first_name(qp->tterm.term_names),
6260e3d5408SPeter Wemm 			   len);
6270e3d5408SPeter Wemm 		}
6280e3d5408SPeter Wemm 	    }
6290e3d5408SPeter Wemm 	}
6300e3d5408SPeter Wemm 
6310e3d5408SPeter Wemm 	/* write or dump all entries */
6320e3d5408SPeter Wemm 	if (!check_only)
6330e3d5408SPeter Wemm 	{
6340e3d5408SPeter Wemm 	    if (!infodump && !capdump)
6350e3d5408SPeter Wemm 	    {
6360e3d5408SPeter Wemm 		_nc_set_writedir(outdir);
6370e3d5408SPeter Wemm 		for_entry_list(qp)
6380e3d5408SPeter Wemm 		    if (matches(namelst, qp->tterm.term_names))
6390e3d5408SPeter Wemm 			write_it(qp);
6400e3d5408SPeter Wemm 	    }
6410e3d5408SPeter Wemm 	    else
6420e3d5408SPeter Wemm 	    {
6430e3d5408SPeter Wemm 		/* this is in case infotocap() generates warnings */
6440e3d5408SPeter Wemm 		_nc_curr_col = _nc_curr_line = -1;
6450e3d5408SPeter Wemm 
6460e3d5408SPeter Wemm 		for_entry_list(qp)
6470e3d5408SPeter Wemm 		    if (matches(namelst, qp->tterm.term_names))
6480e3d5408SPeter Wemm 		    {
6490e3d5408SPeter Wemm 			int	j = qp->cend - qp->cstart;
6500e3d5408SPeter Wemm 			int	len = 0;
6510e3d5408SPeter Wemm 
6520e3d5408SPeter Wemm 			/* this is in case infotocap() generates warnings */
6530e3d5408SPeter Wemm 			_nc_set_type(_nc_first_name(qp->tterm.term_names));
6540e3d5408SPeter Wemm 
6550e3d5408SPeter Wemm 			(void) fseek(tmp_fp, qp->cstart, SEEK_SET);
6560e3d5408SPeter Wemm 			while (j-- )
6570e3d5408SPeter Wemm 			    if (infodump)
6580e3d5408SPeter Wemm 				(void) putchar(fgetc(tmp_fp));
6590e3d5408SPeter Wemm 			    else
6600e3d5408SPeter Wemm 				put_translate(fgetc(tmp_fp));
6610e3d5408SPeter Wemm 
6620e3d5408SPeter Wemm 			len = dump_entry(&qp->tterm, limited, numbers, NULL);
6630e3d5408SPeter Wemm 			for (j = 0; j < qp->nuses; j++)
6640e3d5408SPeter Wemm 			    len += dump_uses((char *)(qp->uses[j].parent), infodump);
6650e3d5408SPeter Wemm 			(void) putchar('\n');
6660e3d5408SPeter Wemm 			if (debug_level != 0 && !limited)
6670e3d5408SPeter Wemm 			    printf("# length=%d\n", len);
6680e3d5408SPeter Wemm 		    }
6690e3d5408SPeter Wemm 		if (!namelst)
6700e3d5408SPeter Wemm 		{
6710e3d5408SPeter Wemm 		    int  c, oldc = '\0';
6720e3d5408SPeter Wemm 		    bool in_comment = FALSE;
6730e3d5408SPeter Wemm 		    bool trailing_comment = FALSE;
6740e3d5408SPeter Wemm 
6750e3d5408SPeter Wemm 		    (void) fseek(tmp_fp, _nc_tail->cend, SEEK_SET);
6760e3d5408SPeter Wemm 		    while ((c = fgetc(tmp_fp)) != EOF)
6770e3d5408SPeter Wemm 		    {
6780e3d5408SPeter Wemm 			if (oldc == '\n') {
6790e3d5408SPeter Wemm 			    if (c == '#') {
6800e3d5408SPeter Wemm 				trailing_comment = TRUE;
6810e3d5408SPeter Wemm 				in_comment = TRUE;
6820e3d5408SPeter Wemm 			    } else {
6830e3d5408SPeter Wemm 				in_comment = FALSE;
6840e3d5408SPeter Wemm 			    }
6850e3d5408SPeter Wemm 			}
6860e3d5408SPeter Wemm 			if (trailing_comment
6870e3d5408SPeter Wemm 			 && (in_comment || (oldc == '\n' && c == '\n')))
6880e3d5408SPeter Wemm 			    putchar(c);
6890e3d5408SPeter Wemm 			oldc = c;
6900e3d5408SPeter Wemm 		    }
6910e3d5408SPeter Wemm 		}
6920e3d5408SPeter Wemm 	    }
6930e3d5408SPeter Wemm 	}
6940e3d5408SPeter Wemm 
6950e3d5408SPeter Wemm 	/* Show the directory into which entries were written, and the total
6960e3d5408SPeter Wemm 	 * number of entries
6970e3d5408SPeter Wemm 	 */
6980e3d5408SPeter Wemm 	if (showsummary
6990e3d5408SPeter Wemm 	 && (!(check_only || infodump || capdump))) {
7000e3d5408SPeter Wemm 		int total = _nc_tic_written();
7010e3d5408SPeter Wemm 		if (total != 0)
7020e3d5408SPeter Wemm 			fprintf(log_fp, "%d entries written to %s\n",
7030e3d5408SPeter Wemm 				total,
7040e3d5408SPeter Wemm 				_nc_tic_dir((char *)0));
7050e3d5408SPeter Wemm 		else
7060e3d5408SPeter Wemm 			fprintf(log_fp, "No entries written\n");
7070e3d5408SPeter Wemm 	}
7080e3d5408SPeter Wemm 	cleanup();
7090e3d5408SPeter Wemm 	return(EXIT_SUCCESS);
7100e3d5408SPeter Wemm }
7110e3d5408SPeter Wemm 
7120e3d5408SPeter Wemm /*
7130e3d5408SPeter Wemm  * This bit of legerdemain turns all the terminfo variable names into
7140e3d5408SPeter Wemm  * references to locations in the arrays Booleans, Numbers, and Strings ---
7150e3d5408SPeter Wemm  * precisely what's needed (see comp_parse.c).
7160e3d5408SPeter Wemm  */
7170e3d5408SPeter Wemm 
7180e3d5408SPeter Wemm TERMINAL *cur_term;	/* tweak to avoid linking lib_cur_term.c */
7190e3d5408SPeter Wemm 
7200e3d5408SPeter Wemm #undef CUR
7210e3d5408SPeter Wemm #define CUR tp->
7220e3d5408SPeter Wemm 
7230e3d5408SPeter Wemm /* other sanity-checks (things that we don't want in the normal
7240e3d5408SPeter Wemm  * logic that reads a terminfo entry)
7250e3d5408SPeter Wemm  */
7260e3d5408SPeter Wemm static void check_termtype(TERMTYPE *tp)
7270e3d5408SPeter Wemm {
7280e3d5408SPeter Wemm 	bool conflict = FALSE;
7290e3d5408SPeter Wemm 	unsigned j, k;
7300e3d5408SPeter Wemm 	char  fkeys[STRCOUNT];
7310e3d5408SPeter Wemm 
7320e3d5408SPeter Wemm 	/*
7330e3d5408SPeter Wemm 	 * A terminal entry may contain more than one keycode assigned to
7340e3d5408SPeter Wemm 	 * a given string (e.g., KEY_END and KEY_LL).  But curses will only
7350e3d5408SPeter Wemm 	 * return one (the last one assigned).
7360e3d5408SPeter Wemm 	 */
7370e3d5408SPeter Wemm 	memset(fkeys, 0, sizeof(fkeys));
7380e3d5408SPeter Wemm 	for (j = 0; _nc_tinfo_fkeys[j].code; j++) {
7390e3d5408SPeter Wemm 	    char *a = tp->Strings[_nc_tinfo_fkeys[j].offset];
7400e3d5408SPeter Wemm 	    bool first = TRUE;
7410e3d5408SPeter Wemm 	    if (!VALID_STRING(a))
7420e3d5408SPeter Wemm 		continue;
7430e3d5408SPeter Wemm 	    for (k = j+1; _nc_tinfo_fkeys[k].code; k++) {
7440e3d5408SPeter Wemm 		char *b = tp->Strings[_nc_tinfo_fkeys[k].offset];
7450e3d5408SPeter Wemm 		if (!VALID_STRING(b)
7460e3d5408SPeter Wemm 		 || fkeys[k])
7470e3d5408SPeter Wemm 		    continue;
7480e3d5408SPeter Wemm 		if (!strcmp(a,b)) {
7490e3d5408SPeter Wemm 		    fkeys[j] = 1;
7500e3d5408SPeter Wemm 		    fkeys[k] = 1;
7510e3d5408SPeter Wemm 		    if (first) {
7520e3d5408SPeter Wemm 			if (!conflict) {
7530e3d5408SPeter Wemm 			    _nc_warning("Conflicting key definitions (using the last)");
7540e3d5408SPeter Wemm 			    conflict = TRUE;
7550e3d5408SPeter Wemm 			}
7560e3d5408SPeter Wemm 			fprintf(stderr, "... %s is the same as %s",
7570e3d5408SPeter Wemm 				keyname(_nc_tinfo_fkeys[j].code),
7580e3d5408SPeter Wemm 				keyname(_nc_tinfo_fkeys[k].code));
7590e3d5408SPeter Wemm 			first = FALSE;
7600e3d5408SPeter Wemm 		    } else {
7610e3d5408SPeter Wemm 			fprintf(stderr, ", %s",
7620e3d5408SPeter Wemm 				keyname(_nc_tinfo_fkeys[k].code));
7630e3d5408SPeter Wemm 		    }
7640e3d5408SPeter Wemm 		}
7650e3d5408SPeter Wemm 	    }
7660e3d5408SPeter Wemm 	    if (!first)
7670e3d5408SPeter Wemm 		fprintf(stderr, "\n");
7680e3d5408SPeter Wemm 	}
7690e3d5408SPeter Wemm 
7700e3d5408SPeter Wemm 	/*
7710e3d5408SPeter Wemm 	 * Quick check for color.  We could also check if the ANSI versus
7720e3d5408SPeter Wemm 	 * non-ANSI strings are misused.
7730e3d5408SPeter Wemm 	 */
7740e3d5408SPeter Wemm 	if ((max_colors > 0) != (max_pairs > 0)
7750e3d5408SPeter Wemm 	 || (max_colors > max_pairs))
7760e3d5408SPeter Wemm 		_nc_warning("inconsistent values for max_colors and max_pairs");
7770e3d5408SPeter Wemm 
7780e3d5408SPeter Wemm 	PAIRED(set_foreground,                  set_background)
7790e3d5408SPeter Wemm 	PAIRED(set_a_foreground,                set_a_background)
7800e3d5408SPeter Wemm 
7810e3d5408SPeter Wemm 	/*
7820e3d5408SPeter Wemm 	 * These may be mismatched because the terminal description relies on
7830e3d5408SPeter Wemm 	 * restoring the cursor visibility by resetting it.
7840e3d5408SPeter Wemm 	 */
7850e3d5408SPeter Wemm 	ANDMISSING(cursor_invisible,            cursor_normal)
7860e3d5408SPeter Wemm 	ANDMISSING(cursor_visible,              cursor_normal)
7870e3d5408SPeter Wemm 
7880e3d5408SPeter Wemm 	/*
7890e3d5408SPeter Wemm 	 * From XSI & O'Reilly, we gather that sc/rc are required if csr is
7900e3d5408SPeter Wemm 	 * given, because the cursor position after the scrolling operation is
7910e3d5408SPeter Wemm 	 * performed is undefined.
7920e3d5408SPeter Wemm 	 */
7930e3d5408SPeter Wemm 	ANDMISSING(change_scroll_region,	save_cursor)
7940e3d5408SPeter Wemm 	ANDMISSING(change_scroll_region,	restore_cursor)
7950e3d5408SPeter Wemm 
7960e3d5408SPeter Wemm 	/*
7970e3d5408SPeter Wemm 	 * Some standard applications (e.g., vi) and some non-curses
7980e3d5408SPeter Wemm 	 * applications (e.g., jove) get confused if we have both ich/ich1 and
7990e3d5408SPeter Wemm 	 * smir/rmir.  Let's be nice and warn about that, too, even though
8000e3d5408SPeter Wemm 	 * ncurses handles it.
8010e3d5408SPeter Wemm 	 */
8020e3d5408SPeter Wemm 	if ((PRESENT(enter_insert_mode) || PRESENT(exit_insert_mode))
8030e3d5408SPeter Wemm 	 && (PRESENT(insert_character)  || PRESENT(parm_ich))) {
8040e3d5408SPeter Wemm 	   _nc_warning("non-curses applications may be confused by ich/ich1 with smir/rmir");
8050e3d5408SPeter Wemm 	}
8060e3d5408SPeter Wemm 
8070e3d5408SPeter Wemm 	/*
8080e3d5408SPeter Wemm 	 * Finally, do the non-verbose checks
8090e3d5408SPeter Wemm 	 */
8100e3d5408SPeter Wemm 	if (save_check_termtype != 0)
8110e3d5408SPeter Wemm 	    save_check_termtype(tp);
8120e3d5408SPeter Wemm }
813