10e3d5408SPeter Wemm /**************************************************************************** 27a69bbfbSPeter Wemm * Copyright (c) 1998,1999,2000,2001 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> 4118259542SPeter Wemm #include <sys/stat.h> 420e3d5408SPeter Wemm 430e3d5408SPeter Wemm #include <dump_entry.h> 440e3d5408SPeter Wemm #include <term_entry.h> 4518259542SPeter Wemm #include <transform.h> 460e3d5408SPeter Wemm 477a69bbfbSPeter Wemm MODULE_ID("$Id: tic.c,v 1.90 2001/04/15 00:21:31 tom Exp $") 480e3d5408SPeter Wemm 490e3d5408SPeter Wemm const char *_nc_progname = "tic"; 500e3d5408SPeter Wemm 510e3d5408SPeter Wemm static FILE *log_fp; 520e3d5408SPeter Wemm static FILE *tmp_fp; 530e3d5408SPeter Wemm static bool showsummary = FALSE; 540e3d5408SPeter Wemm static const char *to_remove; 557a69bbfbSPeter Wemm static int tparm_errs; 560e3d5408SPeter Wemm 570e3d5408SPeter Wemm static void (*save_check_termtype) (TERMTYPE *); 580e3d5408SPeter Wemm static void check_termtype(TERMTYPE * tt); 590e3d5408SPeter Wemm 6018259542SPeter Wemm static const char usage_string[] = "[-V] [-v[n]] [-e names] [-CILNRTcfrswx1] source-file\n"; 610e3d5408SPeter Wemm 6215589c42SPeter Wemm static void 6315589c42SPeter Wemm cleanup(void) 640e3d5408SPeter Wemm { 650e3d5408SPeter Wemm if (tmp_fp != 0) 660e3d5408SPeter Wemm fclose(tmp_fp); 670e3d5408SPeter Wemm if (to_remove != 0) { 680e3d5408SPeter Wemm #if HAVE_REMOVE 690e3d5408SPeter Wemm remove(to_remove); 700e3d5408SPeter Wemm #else 710e3d5408SPeter Wemm unlink(to_remove); 720e3d5408SPeter Wemm #endif 730e3d5408SPeter Wemm } 740e3d5408SPeter Wemm } 750e3d5408SPeter Wemm 7615589c42SPeter Wemm static void 7715589c42SPeter Wemm failed(const char *msg) 780e3d5408SPeter Wemm { 790e3d5408SPeter Wemm perror(msg); 800e3d5408SPeter Wemm cleanup(); 810e3d5408SPeter Wemm exit(EXIT_FAILURE); 820e3d5408SPeter Wemm } 830e3d5408SPeter Wemm 8415589c42SPeter Wemm static void 8515589c42SPeter Wemm usage(void) 860e3d5408SPeter Wemm { 8715589c42SPeter Wemm static const char *const tbl[] = 8815589c42SPeter Wemm { 890e3d5408SPeter Wemm "Options:", 900e3d5408SPeter Wemm " -1 format translation output one capability per line", 910e3d5408SPeter Wemm " -C translate entries to termcap source form", 920e3d5408SPeter Wemm " -I translate entries to terminfo source form", 930e3d5408SPeter Wemm " -L translate entries to full terminfo source form", 940e3d5408SPeter Wemm " -N disable smart defaults for source translation", 950e3d5408SPeter Wemm " -R restrict translation to given terminfo/termcap version", 960e3d5408SPeter Wemm " -T remove size-restrictions on compiled description", 9718259542SPeter Wemm " -V print version", 9815589c42SPeter Wemm #if NCURSES_XNAMES 9915589c42SPeter Wemm " -a retain commented-out capabilities (sets -x also)", 10015589c42SPeter Wemm #endif 1010e3d5408SPeter Wemm " -c check only, validate input without compiling or translating", 1020e3d5408SPeter Wemm " -f format complex strings for readability", 1030e3d5408SPeter Wemm " -G format %{number} to %'char'", 1040e3d5408SPeter Wemm " -g format %'char' to %{number}", 1050e3d5408SPeter Wemm " -e<names> translate/compile only entries named by comma-separated list", 1060e3d5408SPeter Wemm " -o<dir> set output directory for compiled entry writes", 1070e3d5408SPeter Wemm " -r force resolution of all use entries in source translation", 1080e3d5408SPeter Wemm " -s print summary statistics", 1090e3d5408SPeter Wemm " -v[n] set verbosity level", 1100e3d5408SPeter Wemm " -w[n] set format width for translation output", 1110e3d5408SPeter Wemm #if NCURSES_XNAMES 1120e3d5408SPeter Wemm " -x treat unknown capabilities as user-defined", 1130e3d5408SPeter Wemm #endif 1140e3d5408SPeter Wemm "", 1150e3d5408SPeter Wemm "Parameters:", 1160e3d5408SPeter Wemm " <file> file to translate or compile" 1170e3d5408SPeter Wemm }; 1180e3d5408SPeter Wemm size_t j; 1190e3d5408SPeter Wemm 12015589c42SPeter Wemm fprintf(stderr, "Usage: %s %s\n", _nc_progname, usage_string); 12118259542SPeter Wemm for (j = 0; j < SIZEOF(tbl); j++) { 12215589c42SPeter Wemm fputs(tbl[j], stderr); 12315589c42SPeter Wemm putc('\n', stderr); 12415589c42SPeter Wemm } 1250e3d5408SPeter Wemm exit(EXIT_FAILURE); 1260e3d5408SPeter Wemm } 1270e3d5408SPeter Wemm 1280e3d5408SPeter Wemm #define L_BRACE '{' 1290e3d5408SPeter Wemm #define R_BRACE '}' 1300e3d5408SPeter Wemm #define S_QUOTE '\''; 1310e3d5408SPeter Wemm 13215589c42SPeter Wemm static void 13315589c42SPeter Wemm write_it(ENTRY * ep) 1340e3d5408SPeter Wemm { 1350e3d5408SPeter Wemm unsigned n; 1360e3d5408SPeter Wemm int ch; 1370e3d5408SPeter Wemm char *s, *d, *t; 1380e3d5408SPeter Wemm char result[MAX_ENTRY_SIZE]; 1390e3d5408SPeter Wemm 1400e3d5408SPeter Wemm /* 1410e3d5408SPeter Wemm * Look for strings that contain %{number}, convert them to %'char', 1420e3d5408SPeter Wemm * which is shorter and runs a little faster. 1430e3d5408SPeter Wemm */ 1440e3d5408SPeter Wemm for (n = 0; n < STRCOUNT; n++) { 1450e3d5408SPeter Wemm s = ep->tterm.Strings[n]; 1460e3d5408SPeter Wemm if (VALID_STRING(s) 1470e3d5408SPeter Wemm && strchr(s, L_BRACE) != 0) { 1480e3d5408SPeter Wemm d = result; 1490e3d5408SPeter Wemm t = s; 1500e3d5408SPeter Wemm while ((ch = *t++) != 0) { 1510e3d5408SPeter Wemm *d++ = ch; 1520e3d5408SPeter Wemm if (ch == '\\') { 1530e3d5408SPeter Wemm *d++ = *t++; 1540e3d5408SPeter Wemm } else if ((ch == '%') 1550e3d5408SPeter Wemm && (*t == L_BRACE)) { 1560e3d5408SPeter Wemm char *v = 0; 1570e3d5408SPeter Wemm long value = strtol(t + 1, &v, 0); 1580e3d5408SPeter Wemm if (v != 0 1590e3d5408SPeter Wemm && *v == R_BRACE 1600e3d5408SPeter Wemm && value > 0 1610e3d5408SPeter Wemm && value != '\\' /* FIXME */ 1620e3d5408SPeter Wemm && value < 127 1630e3d5408SPeter Wemm && isprint((int) value)) { 1640e3d5408SPeter Wemm *d++ = S_QUOTE; 1650e3d5408SPeter Wemm *d++ = (int) value; 1660e3d5408SPeter Wemm *d++ = S_QUOTE; 1670e3d5408SPeter Wemm t = (v + 1); 1680e3d5408SPeter Wemm } 1690e3d5408SPeter Wemm } 1700e3d5408SPeter Wemm } 1710e3d5408SPeter Wemm *d = 0; 1720e3d5408SPeter Wemm if (strlen(result) < strlen(s)) 1730e3d5408SPeter Wemm strcpy(s, result); 1740e3d5408SPeter Wemm } 1750e3d5408SPeter Wemm } 1760e3d5408SPeter Wemm 1770e3d5408SPeter Wemm _nc_set_type(_nc_first_name(ep->tterm.term_names)); 1780e3d5408SPeter Wemm _nc_curr_line = ep->startline; 1790e3d5408SPeter Wemm _nc_write_entry(&ep->tterm); 1800e3d5408SPeter Wemm } 1810e3d5408SPeter Wemm 18215589c42SPeter Wemm static bool 18315589c42SPeter Wemm immedhook(ENTRY * ep GCC_UNUSED) 1840e3d5408SPeter Wemm /* write out entries with no use capabilities immediately to save storage */ 1850e3d5408SPeter Wemm { 18618259542SPeter Wemm #if !HAVE_BIG_CORE 1870e3d5408SPeter Wemm /* 1880e3d5408SPeter Wemm * This is strictly a core-economy kluge. The really clean way to handle 1890e3d5408SPeter Wemm * compilation is to slurp the whole file into core and then do all the 1900e3d5408SPeter Wemm * name-collision checks and entry writes in one swell foop. But the 1910e3d5408SPeter Wemm * terminfo master file is large enough that some core-poor systems swap 1920e3d5408SPeter Wemm * like crazy when you compile it this way...there have been reports of 1930e3d5408SPeter Wemm * this process taking *three hours*, rather than the twenty seconds or 1940e3d5408SPeter Wemm * less typical on my development box. 1950e3d5408SPeter Wemm * 1960e3d5408SPeter Wemm * So. This hook *immediately* writes out the referenced entry if it 1970e3d5408SPeter Wemm * has no use capabilities. The compiler main loop refrains from 1980e3d5408SPeter Wemm * adding the entry to the in-core list when this hook fires. If some 1990e3d5408SPeter Wemm * other entry later needs to reference an entry that got written 2000e3d5408SPeter Wemm * immediately, that's OK; the resolution code will fetch it off disk 2010e3d5408SPeter Wemm * when it can't find it in core. 2020e3d5408SPeter Wemm * 2030e3d5408SPeter Wemm * Name collisions will still be detected, just not as cleanly. The 2040e3d5408SPeter Wemm * write_entry() code complains before overwriting an entry that 2050e3d5408SPeter Wemm * postdates the time of tic's first call to write_entry(). Thus 2060e3d5408SPeter Wemm * it will complain about overwriting entries newly made during the 2070e3d5408SPeter Wemm * tic run, but not about overwriting ones that predate it. 2080e3d5408SPeter Wemm * 2090e3d5408SPeter Wemm * The reason this is a hook, and not in line with the rest of the 2100e3d5408SPeter Wemm * compiler code, is that the support for termcap fallback cannot assume 2110e3d5408SPeter Wemm * it has anywhere to spool out these entries! 2120e3d5408SPeter Wemm * 2130e3d5408SPeter Wemm * The _nc_set_type() call here requires a compensating one in 2140e3d5408SPeter Wemm * _nc_parse_entry(). 2150e3d5408SPeter Wemm * 2160e3d5408SPeter Wemm * If you define HAVE_BIG_CORE, you'll disable this kluge. This will 2170e3d5408SPeter Wemm * make tic a bit faster (because the resolution code won't have to do 2180e3d5408SPeter Wemm * disk I/O nearly as often). 2190e3d5408SPeter Wemm */ 22015589c42SPeter Wemm if (ep->nuses == 0) { 2210e3d5408SPeter Wemm int oldline = _nc_curr_line; 2220e3d5408SPeter Wemm 2230e3d5408SPeter Wemm write_it(ep); 2240e3d5408SPeter Wemm _nc_curr_line = oldline; 2250e3d5408SPeter Wemm free(ep->tterm.str_table); 2260e3d5408SPeter Wemm return (TRUE); 2270e3d5408SPeter Wemm } 2280e3d5408SPeter Wemm #endif /* HAVE_BIG_CORE */ 2290e3d5408SPeter Wemm return (FALSE); 2300e3d5408SPeter Wemm } 2310e3d5408SPeter Wemm 23215589c42SPeter Wemm static void 23315589c42SPeter Wemm put_translate(int c) 2340e3d5408SPeter Wemm /* emit a comment char, translating terminfo names to termcap names */ 2350e3d5408SPeter Wemm { 2360e3d5408SPeter Wemm static bool in_name = FALSE; 23715589c42SPeter Wemm static size_t have, used; 23815589c42SPeter Wemm static char *namebuf, *suffix; 2390e3d5408SPeter Wemm 24015589c42SPeter Wemm if (in_name) { 24115589c42SPeter Wemm if (used + 1 >= have) { 24215589c42SPeter Wemm have += 132; 24315589c42SPeter Wemm namebuf = typeRealloc(char, have, namebuf); 24415589c42SPeter Wemm suffix = typeRealloc(char, have, suffix); 2450e3d5408SPeter Wemm } 24615589c42SPeter Wemm if (c == '\n' || c == '@') { 24715589c42SPeter Wemm namebuf[used++] = '\0'; 2480e3d5408SPeter Wemm (void) putchar('<'); 2490e3d5408SPeter Wemm (void) fputs(namebuf, stdout); 2500e3d5408SPeter Wemm putchar(c); 2510e3d5408SPeter Wemm in_name = FALSE; 25215589c42SPeter Wemm } else if (c != '>') { 25315589c42SPeter Wemm namebuf[used++] = c; 25415589c42SPeter Wemm } else { /* ah! candidate name! */ 2550e3d5408SPeter Wemm char *up; 2560e3d5408SPeter Wemm NCURSES_CONST char *tp; 2570e3d5408SPeter Wemm 25815589c42SPeter Wemm namebuf[used++] = '\0'; 2590e3d5408SPeter Wemm in_name = FALSE; 2600e3d5408SPeter Wemm 2610e3d5408SPeter Wemm suffix[0] = '\0'; 2620e3d5408SPeter Wemm if ((up = strchr(namebuf, '#')) != 0 2630e3d5408SPeter Wemm || (up = strchr(namebuf, '=')) != 0 26415589c42SPeter Wemm || ((up = strchr(namebuf, '@')) != 0 && up[1] == '>')) { 2650e3d5408SPeter Wemm (void) strcpy(suffix, up); 2660e3d5408SPeter Wemm *up = '\0'; 2670e3d5408SPeter Wemm } 2680e3d5408SPeter Wemm 26915589c42SPeter Wemm if ((tp = nametrans(namebuf)) != 0) { 2700e3d5408SPeter Wemm (void) putchar(':'); 2710e3d5408SPeter Wemm (void) fputs(tp, stdout); 2720e3d5408SPeter Wemm (void) fputs(suffix, stdout); 2730e3d5408SPeter Wemm (void) putchar(':'); 27415589c42SPeter Wemm } else { 2750e3d5408SPeter Wemm /* couldn't find a translation, just dump the name */ 2760e3d5408SPeter Wemm (void) putchar('<'); 2770e3d5408SPeter Wemm (void) fputs(namebuf, stdout); 2780e3d5408SPeter Wemm (void) fputs(suffix, stdout); 2790e3d5408SPeter Wemm (void) putchar('>'); 2800e3d5408SPeter Wemm } 28115589c42SPeter Wemm } 28215589c42SPeter Wemm } else { 28315589c42SPeter Wemm used = 0; 28415589c42SPeter Wemm if (c == '<') { 28515589c42SPeter Wemm in_name = TRUE; 28615589c42SPeter Wemm } else { 28715589c42SPeter Wemm putchar(c); 28815589c42SPeter Wemm } 2890e3d5408SPeter Wemm } 2900e3d5408SPeter Wemm } 2910e3d5408SPeter Wemm 2920e3d5408SPeter Wemm /* Returns a string, stripped of leading/trailing whitespace */ 29315589c42SPeter Wemm static char * 29415589c42SPeter Wemm stripped(char *src) 2950e3d5408SPeter Wemm { 2967a69bbfbSPeter Wemm while (isspace(CharOf(*src))) 2970e3d5408SPeter Wemm src++; 2980e3d5408SPeter Wemm if (*src != '\0') { 2990e3d5408SPeter Wemm char *dst = strcpy(malloc(strlen(src) + 1), src); 3000e3d5408SPeter Wemm size_t len = strlen(dst); 3017a69bbfbSPeter Wemm while (--len != 0 && isspace(CharOf(dst[len]))) 3020e3d5408SPeter Wemm dst[len] = '\0'; 3030e3d5408SPeter Wemm return dst; 3040e3d5408SPeter Wemm } 3050e3d5408SPeter Wemm return 0; 3060e3d5408SPeter Wemm } 3070e3d5408SPeter Wemm 30818259542SPeter Wemm static FILE * 30918259542SPeter Wemm open_input(const char *filename) 31018259542SPeter Wemm { 31118259542SPeter Wemm FILE *fp = fopen(filename, "r"); 31218259542SPeter Wemm struct stat sb; 31318259542SPeter Wemm 31418259542SPeter Wemm if (fp == 0) { 31518259542SPeter Wemm fprintf(stderr, "%s: Can't open %s\n", _nc_progname, filename); 31618259542SPeter Wemm exit(EXIT_FAILURE); 31718259542SPeter Wemm } 31818259542SPeter Wemm if (fstat(fileno(fp), &sb) < 0 31918259542SPeter Wemm || (sb.st_mode & S_IFMT) != S_IFREG) { 32018259542SPeter Wemm fprintf(stderr, "%s: %s is not a file\n", _nc_progname, filename); 32118259542SPeter Wemm exit(EXIT_FAILURE); 32218259542SPeter Wemm } 32318259542SPeter Wemm return fp; 32418259542SPeter Wemm } 32518259542SPeter Wemm 3260e3d5408SPeter Wemm /* Parse the "-e" option-value into a list of names */ 32715589c42SPeter Wemm static const char ** 32815589c42SPeter Wemm make_namelist(char *src) 3290e3d5408SPeter Wemm { 3300e3d5408SPeter Wemm const char **dst = 0; 3310e3d5408SPeter Wemm 3320e3d5408SPeter Wemm char *s, *base; 3330e3d5408SPeter Wemm unsigned pass, n, nn; 3340e3d5408SPeter Wemm char buffer[BUFSIZ]; 3350e3d5408SPeter Wemm 3360e3d5408SPeter Wemm if (src == 0) { 3370e3d5408SPeter Wemm /* EMPTY */ ; 3380e3d5408SPeter Wemm } else if (strchr(src, '/') != 0) { /* a filename */ 33918259542SPeter Wemm FILE *fp = open_input(src); 3400e3d5408SPeter Wemm 3410e3d5408SPeter Wemm for (pass = 1; pass <= 2; pass++) { 3420e3d5408SPeter Wemm nn = 0; 3430e3d5408SPeter Wemm while (fgets(buffer, sizeof(buffer), fp) != 0) { 3440e3d5408SPeter Wemm if ((s = stripped(buffer)) != 0) { 3450e3d5408SPeter Wemm if (dst != 0) 3460e3d5408SPeter Wemm dst[nn] = s; 3470e3d5408SPeter Wemm nn++; 3480e3d5408SPeter Wemm } 3490e3d5408SPeter Wemm } 3500e3d5408SPeter Wemm if (pass == 1) { 35115589c42SPeter Wemm dst = typeCalloc(const char *, nn + 1); 3520e3d5408SPeter Wemm rewind(fp); 3530e3d5408SPeter Wemm } 3540e3d5408SPeter Wemm } 3550e3d5408SPeter Wemm fclose(fp); 3560e3d5408SPeter Wemm } else { /* literal list of names */ 3570e3d5408SPeter Wemm for (pass = 1; pass <= 2; pass++) { 3580e3d5408SPeter Wemm for (n = nn = 0, base = src;; n++) { 3590e3d5408SPeter Wemm int mark = src[n]; 3600e3d5408SPeter Wemm if (mark == ',' || mark == '\0') { 3610e3d5408SPeter Wemm if (pass == 1) { 3620e3d5408SPeter Wemm nn++; 3630e3d5408SPeter Wemm } else { 3640e3d5408SPeter Wemm src[n] = '\0'; 3650e3d5408SPeter Wemm if ((s = stripped(base)) != 0) 3660e3d5408SPeter Wemm dst[nn++] = s; 3670e3d5408SPeter Wemm base = &src[n + 1]; 3680e3d5408SPeter Wemm } 3690e3d5408SPeter Wemm } 3700e3d5408SPeter Wemm if (mark == '\0') 3710e3d5408SPeter Wemm break; 3720e3d5408SPeter Wemm } 3730e3d5408SPeter Wemm if (pass == 1) 37415589c42SPeter Wemm dst = typeCalloc(const char *, nn + 1); 3750e3d5408SPeter Wemm } 3760e3d5408SPeter Wemm } 3770e3d5408SPeter Wemm if (showsummary) { 3780e3d5408SPeter Wemm fprintf(log_fp, "Entries that will be compiled:\n"); 3790e3d5408SPeter Wemm for (n = 0; dst[n] != 0; n++) 3800e3d5408SPeter Wemm fprintf(log_fp, "%d:%s\n", n + 1, dst[n]); 3810e3d5408SPeter Wemm } 3820e3d5408SPeter Wemm return dst; 3830e3d5408SPeter Wemm } 3840e3d5408SPeter Wemm 38515589c42SPeter Wemm static bool 38615589c42SPeter Wemm matches(const char **needle, const char *haystack) 3870e3d5408SPeter Wemm /* does entry in needle list match |-separated field in haystack? */ 3880e3d5408SPeter Wemm { 3890e3d5408SPeter Wemm bool code = FALSE; 3900e3d5408SPeter Wemm size_t n; 3910e3d5408SPeter Wemm 39215589c42SPeter Wemm if (needle != 0) { 39315589c42SPeter Wemm for (n = 0; needle[n] != 0; n++) { 39415589c42SPeter Wemm if (_nc_name_match(haystack, needle[n], "|")) { 3950e3d5408SPeter Wemm code = TRUE; 3960e3d5408SPeter Wemm break; 3970e3d5408SPeter Wemm } 3980e3d5408SPeter Wemm } 39915589c42SPeter Wemm } else 4000e3d5408SPeter Wemm code = TRUE; 4010e3d5408SPeter Wemm return (code); 4020e3d5408SPeter Wemm } 4030e3d5408SPeter Wemm 40415589c42SPeter Wemm static FILE * 40515589c42SPeter Wemm open_tempfile(char *name) 40615589c42SPeter Wemm { 40715589c42SPeter Wemm FILE *result = 0; 40815589c42SPeter Wemm #if HAVE_MKSTEMP 40915589c42SPeter Wemm int fd = mkstemp(name); 41015589c42SPeter Wemm if (fd >= 0) 41115589c42SPeter Wemm result = fdopen(fd, "w"); 41215589c42SPeter Wemm #else 41315589c42SPeter Wemm if (tmpnam(name) != 0) 41415589c42SPeter Wemm result = fopen(name, "w"); 41515589c42SPeter Wemm #endif 41615589c42SPeter Wemm return result; 41715589c42SPeter Wemm } 41815589c42SPeter Wemm 41915589c42SPeter Wemm int 42015589c42SPeter Wemm main(int argc, char *argv[]) 4210e3d5408SPeter Wemm { 4220e3d5408SPeter Wemm char my_tmpname[PATH_MAX]; 4230e3d5408SPeter Wemm int v_opt = -1, debug_level; 4240e3d5408SPeter Wemm int smart_defaults = TRUE; 4250e3d5408SPeter Wemm char *termcap; 4260e3d5408SPeter Wemm ENTRY *qp; 4270e3d5408SPeter Wemm 4280e3d5408SPeter Wemm int this_opt, last_opt = '?'; 4290e3d5408SPeter Wemm 4300e3d5408SPeter Wemm int outform = F_TERMINFO; /* output format */ 4310e3d5408SPeter Wemm int sortmode = S_TERMINFO; /* sort_mode */ 4320e3d5408SPeter Wemm 4330e3d5408SPeter Wemm int width = 60; 4340e3d5408SPeter Wemm bool formatted = FALSE; /* reformat complex strings? */ 4350e3d5408SPeter Wemm int numbers = 0; /* format "%'char'" to/from "%{number}" */ 4360e3d5408SPeter Wemm bool infodump = FALSE; /* running as captoinfo? */ 4370e3d5408SPeter Wemm bool capdump = FALSE; /* running as infotocap? */ 4380e3d5408SPeter Wemm bool forceresolve = FALSE; /* force resolution */ 4390e3d5408SPeter Wemm bool limited = TRUE; 4400e3d5408SPeter Wemm char *tversion = (char *) NULL; 4410e3d5408SPeter Wemm const char *source_file = "terminfo"; 4420e3d5408SPeter Wemm const char **namelst = 0; 4430e3d5408SPeter Wemm char *outdir = (char *) NULL; 4440e3d5408SPeter Wemm bool check_only = FALSE; 4450e3d5408SPeter Wemm 4460e3d5408SPeter Wemm log_fp = stderr; 4470e3d5408SPeter Wemm 44818259542SPeter Wemm _nc_progname = _nc_basename(argv[0]); 4490e3d5408SPeter Wemm 45018259542SPeter Wemm if ((infodump = (strcmp(_nc_progname, PROG_CAPTOINFO) == 0)) != FALSE) { 45115589c42SPeter Wemm outform = F_TERMINFO; 45215589c42SPeter Wemm sortmode = S_TERMINFO; 45315589c42SPeter Wemm } 45418259542SPeter Wemm if ((capdump = (strcmp(_nc_progname, PROG_INFOTOCAP) == 0)) != FALSE) { 45515589c42SPeter Wemm outform = F_TERMCAP; 45615589c42SPeter Wemm sortmode = S_TERMCAP; 45715589c42SPeter Wemm } 4580e3d5408SPeter Wemm #if NCURSES_XNAMES 4590e3d5408SPeter Wemm use_extended_names(FALSE); 4600e3d5408SPeter Wemm #endif 4610e3d5408SPeter Wemm 4620e3d5408SPeter Wemm /* 4630e3d5408SPeter Wemm * Processing arguments is a little complicated, since someone made a 4640e3d5408SPeter Wemm * design decision to allow the numeric values for -w, -v options to 4650e3d5408SPeter Wemm * be optional. 4660e3d5408SPeter Wemm */ 46715589c42SPeter Wemm while ((this_opt = getopt(argc, argv, 46815589c42SPeter Wemm "0123456789CILNR:TVace:fGgo:rsvwx")) != EOF) { 4690e3d5408SPeter Wemm if (isdigit(this_opt)) { 4700e3d5408SPeter Wemm switch (last_opt) { 4710e3d5408SPeter Wemm case 'v': 4720e3d5408SPeter Wemm v_opt = (v_opt * 10) + (this_opt - '0'); 4730e3d5408SPeter Wemm break; 4740e3d5408SPeter Wemm case 'w': 4750e3d5408SPeter Wemm width = (width * 10) + (this_opt - '0'); 4760e3d5408SPeter Wemm break; 4770e3d5408SPeter Wemm default: 4780e3d5408SPeter Wemm if (this_opt != '1') 4790e3d5408SPeter Wemm usage(); 4800e3d5408SPeter Wemm last_opt = this_opt; 4810e3d5408SPeter Wemm width = 0; 4820e3d5408SPeter Wemm } 4830e3d5408SPeter Wemm continue; 4840e3d5408SPeter Wemm } 4850e3d5408SPeter Wemm switch (this_opt) { 4860e3d5408SPeter Wemm case 'C': 4870e3d5408SPeter Wemm capdump = TRUE; 4880e3d5408SPeter Wemm outform = F_TERMCAP; 4890e3d5408SPeter Wemm sortmode = S_TERMCAP; 4900e3d5408SPeter Wemm break; 4910e3d5408SPeter Wemm case 'I': 4920e3d5408SPeter Wemm infodump = TRUE; 4930e3d5408SPeter Wemm outform = F_TERMINFO; 4940e3d5408SPeter Wemm sortmode = S_TERMINFO; 4950e3d5408SPeter Wemm break; 4960e3d5408SPeter Wemm case 'L': 4970e3d5408SPeter Wemm infodump = TRUE; 4980e3d5408SPeter Wemm outform = F_VARIABLE; 4990e3d5408SPeter Wemm sortmode = S_VARIABLE; 5000e3d5408SPeter Wemm break; 5010e3d5408SPeter Wemm case 'N': 5020e3d5408SPeter Wemm smart_defaults = FALSE; 5030e3d5408SPeter Wemm break; 5040e3d5408SPeter Wemm case 'R': 5050e3d5408SPeter Wemm tversion = optarg; 5060e3d5408SPeter Wemm break; 5070e3d5408SPeter Wemm case 'T': 5080e3d5408SPeter Wemm limited = FALSE; 5090e3d5408SPeter Wemm break; 5100e3d5408SPeter Wemm case 'V': 51118259542SPeter Wemm puts(curses_version()); 5120e3d5408SPeter Wemm return EXIT_SUCCESS; 5130e3d5408SPeter Wemm case 'c': 5140e3d5408SPeter Wemm check_only = TRUE; 5150e3d5408SPeter Wemm break; 5160e3d5408SPeter Wemm case 'e': 5170e3d5408SPeter Wemm namelst = make_namelist(optarg); 5180e3d5408SPeter Wemm break; 5190e3d5408SPeter Wemm case 'f': 5200e3d5408SPeter Wemm formatted = TRUE; 5210e3d5408SPeter Wemm break; 5220e3d5408SPeter Wemm case 'G': 5230e3d5408SPeter Wemm numbers = 1; 5240e3d5408SPeter Wemm break; 5250e3d5408SPeter Wemm case 'g': 5260e3d5408SPeter Wemm numbers = -1; 5270e3d5408SPeter Wemm break; 5280e3d5408SPeter Wemm case 'o': 5290e3d5408SPeter Wemm outdir = optarg; 5300e3d5408SPeter Wemm break; 5310e3d5408SPeter Wemm case 'r': 5320e3d5408SPeter Wemm forceresolve = TRUE; 5330e3d5408SPeter Wemm break; 5340e3d5408SPeter Wemm case 's': 5350e3d5408SPeter Wemm showsummary = TRUE; 5360e3d5408SPeter Wemm break; 5370e3d5408SPeter Wemm case 'v': 5380e3d5408SPeter Wemm v_opt = 0; 5390e3d5408SPeter Wemm break; 5400e3d5408SPeter Wemm case 'w': 5410e3d5408SPeter Wemm width = 0; 5420e3d5408SPeter Wemm break; 5430e3d5408SPeter Wemm #if NCURSES_XNAMES 54415589c42SPeter Wemm case 'a': 54515589c42SPeter Wemm _nc_disable_period = TRUE; 54615589c42SPeter Wemm /* FALLTHRU */ 5470e3d5408SPeter Wemm case 'x': 5480e3d5408SPeter Wemm use_extended_names(TRUE); 5490e3d5408SPeter Wemm break; 5500e3d5408SPeter Wemm #endif 5510e3d5408SPeter Wemm default: 5520e3d5408SPeter Wemm usage(); 5530e3d5408SPeter Wemm } 5540e3d5408SPeter Wemm last_opt = this_opt; 5550e3d5408SPeter Wemm } 5560e3d5408SPeter Wemm 5570e3d5408SPeter Wemm debug_level = (v_opt > 0) ? v_opt : (v_opt == 0); 55815589c42SPeter Wemm set_trace_level(debug_level); 5590e3d5408SPeter Wemm 56015589c42SPeter Wemm if (_nc_tracing) { 5610e3d5408SPeter Wemm save_check_termtype = _nc_check_termtype; 5620e3d5408SPeter Wemm _nc_check_termtype = check_termtype; 5630e3d5408SPeter Wemm } 56418259542SPeter Wemm #if !HAVE_BIG_CORE 5650e3d5408SPeter Wemm /* 5660e3d5408SPeter Wemm * Aaargh! immedhook seriously hoses us! 5670e3d5408SPeter Wemm * 5680e3d5408SPeter Wemm * One problem with immedhook is it means we can't do -e. Problem 5690e3d5408SPeter Wemm * is that we can't guarantee that for each terminal listed, all the 5700e3d5408SPeter Wemm * terminals it depends on will have been kept in core for reference 5710e3d5408SPeter Wemm * resolution -- in fact it's certain the primitive types at the end 5720e3d5408SPeter Wemm * of reference chains *won't* be in core unless they were explicitly 5730e3d5408SPeter Wemm * in the select list themselves. 5740e3d5408SPeter Wemm */ 57515589c42SPeter Wemm if (namelst && (!infodump && !capdump)) { 5760e3d5408SPeter Wemm (void) fprintf(stderr, 5770e3d5408SPeter Wemm "Sorry, -e can't be used without -I or -C\n"); 5780e3d5408SPeter Wemm cleanup(); 5790e3d5408SPeter Wemm return EXIT_FAILURE; 5800e3d5408SPeter Wemm } 5810e3d5408SPeter Wemm #endif /* HAVE_BIG_CORE */ 5820e3d5408SPeter Wemm 5830e3d5408SPeter Wemm if (optind < argc) { 5840e3d5408SPeter Wemm source_file = argv[optind++]; 5850e3d5408SPeter Wemm if (optind < argc) { 5860e3d5408SPeter Wemm fprintf(stderr, 5870e3d5408SPeter Wemm "%s: Too many file names. Usage:\n\t%s %s", 5880e3d5408SPeter Wemm _nc_progname, 5890e3d5408SPeter Wemm _nc_progname, 5900e3d5408SPeter Wemm usage_string); 5910e3d5408SPeter Wemm return EXIT_FAILURE; 5920e3d5408SPeter Wemm } 5930e3d5408SPeter Wemm } else { 5940e3d5408SPeter Wemm if (infodump == TRUE) { 5950e3d5408SPeter Wemm /* captoinfo's no-argument case */ 5960e3d5408SPeter Wemm source_file = "/etc/termcap"; 5970e3d5408SPeter Wemm if ((termcap = getenv("TERMCAP")) != 0 5980e3d5408SPeter Wemm && (namelst = make_namelist(getenv("TERM"))) != 0) { 5990e3d5408SPeter Wemm if (access(termcap, F_OK) == 0) { 6000e3d5408SPeter Wemm /* file exists */ 6010e3d5408SPeter Wemm source_file = termcap; 60218259542SPeter Wemm } else if ((tmp_fp = open_tempfile(strcpy(my_tmpname, 60318259542SPeter Wemm "/tmp/XXXXXX"))) 60418259542SPeter Wemm != 0) { 60515589c42SPeter Wemm source_file = my_tmpname; 6060e3d5408SPeter Wemm fprintf(tmp_fp, "%s\n", termcap); 6070e3d5408SPeter Wemm fclose(tmp_fp); 60818259542SPeter Wemm tmp_fp = open_input(source_file); 6090e3d5408SPeter Wemm to_remove = source_file; 6100e3d5408SPeter Wemm } else { 6110e3d5408SPeter Wemm failed("tmpnam"); 6120e3d5408SPeter Wemm } 6130e3d5408SPeter Wemm } 6140e3d5408SPeter Wemm } else { 6150e3d5408SPeter Wemm /* tic */ 6160e3d5408SPeter Wemm fprintf(stderr, 6170e3d5408SPeter Wemm "%s: File name needed. Usage:\n\t%s %s", 6180e3d5408SPeter Wemm _nc_progname, 6190e3d5408SPeter Wemm _nc_progname, 6200e3d5408SPeter Wemm usage_string); 6210e3d5408SPeter Wemm cleanup(); 6220e3d5408SPeter Wemm return EXIT_FAILURE; 6230e3d5408SPeter Wemm } 6240e3d5408SPeter Wemm } 6250e3d5408SPeter Wemm 62618259542SPeter Wemm if (tmp_fp == 0) 62718259542SPeter Wemm tmp_fp = open_input(source_file); 6280e3d5408SPeter Wemm 6290e3d5408SPeter Wemm if (infodump) 6300e3d5408SPeter Wemm dump_init(tversion, 6310e3d5408SPeter Wemm smart_defaults 6320e3d5408SPeter Wemm ? outform 6330e3d5408SPeter Wemm : F_LITERAL, 6340e3d5408SPeter Wemm sortmode, width, debug_level, formatted); 6350e3d5408SPeter Wemm else if (capdump) 6360e3d5408SPeter Wemm dump_init(tversion, 6370e3d5408SPeter Wemm outform, 6380e3d5408SPeter Wemm sortmode, width, debug_level, FALSE); 6390e3d5408SPeter Wemm 6400e3d5408SPeter Wemm /* parse entries out of the source file */ 6410e3d5408SPeter Wemm _nc_set_source(source_file); 64218259542SPeter Wemm #if !HAVE_BIG_CORE 6430e3d5408SPeter Wemm if (!(check_only || infodump || capdump)) 6440e3d5408SPeter Wemm _nc_set_writedir(outdir); 6450e3d5408SPeter Wemm #endif /* HAVE_BIG_CORE */ 6460e3d5408SPeter Wemm _nc_read_entry_source(tmp_fp, (char *) NULL, 6470e3d5408SPeter Wemm !smart_defaults, FALSE, 6480e3d5408SPeter Wemm (check_only || infodump || capdump) ? NULLHOOK : immedhook); 6490e3d5408SPeter Wemm 6500e3d5408SPeter Wemm /* do use resolution */ 6510e3d5408SPeter Wemm if (check_only || (!infodump && !capdump) || forceresolve) { 65215589c42SPeter Wemm if (!_nc_resolve_uses(TRUE) && !check_only) { 6530e3d5408SPeter Wemm cleanup(); 6540e3d5408SPeter Wemm return EXIT_FAILURE; 6550e3d5408SPeter Wemm } 6560e3d5408SPeter Wemm } 6570e3d5408SPeter Wemm 6580e3d5408SPeter Wemm /* length check */ 65915589c42SPeter Wemm if (check_only && (capdump || infodump)) { 66015589c42SPeter Wemm for_entry_list(qp) { 66115589c42SPeter Wemm if (matches(namelst, qp->tterm.term_names)) { 6620e3d5408SPeter Wemm int len = fmt_entry(&qp->tterm, NULL, TRUE, infodump, numbers); 6630e3d5408SPeter Wemm 6640e3d5408SPeter Wemm if (len > (infodump ? MAX_TERMINFO_LENGTH : MAX_TERMCAP_LENGTH)) 6650e3d5408SPeter Wemm (void) fprintf(stderr, 6660e3d5408SPeter Wemm "warning: resolved %s entry is %d bytes long\n", 6670e3d5408SPeter Wemm _nc_first_name(qp->tterm.term_names), 6680e3d5408SPeter Wemm len); 6690e3d5408SPeter Wemm } 6700e3d5408SPeter Wemm } 6710e3d5408SPeter Wemm } 6720e3d5408SPeter Wemm 6730e3d5408SPeter Wemm /* write or dump all entries */ 67415589c42SPeter Wemm if (!check_only) { 67515589c42SPeter Wemm if (!infodump && !capdump) { 6760e3d5408SPeter Wemm _nc_set_writedir(outdir); 67715589c42SPeter Wemm for_entry_list(qp) { 6780e3d5408SPeter Wemm if (matches(namelst, qp->tterm.term_names)) 6790e3d5408SPeter Wemm write_it(qp); 6800e3d5408SPeter Wemm } 68115589c42SPeter Wemm } else { 6820e3d5408SPeter Wemm /* this is in case infotocap() generates warnings */ 6830e3d5408SPeter Wemm _nc_curr_col = _nc_curr_line = -1; 6840e3d5408SPeter Wemm 68515589c42SPeter Wemm for_entry_list(qp) { 68615589c42SPeter Wemm if (matches(namelst, qp->tterm.term_names)) { 6870e3d5408SPeter Wemm int j = qp->cend - qp->cstart; 6880e3d5408SPeter Wemm int len = 0; 6890e3d5408SPeter Wemm 6900e3d5408SPeter Wemm /* this is in case infotocap() generates warnings */ 6910e3d5408SPeter Wemm _nc_set_type(_nc_first_name(qp->tterm.term_names)); 6920e3d5408SPeter Wemm 6930e3d5408SPeter Wemm (void) fseek(tmp_fp, qp->cstart, SEEK_SET); 69415589c42SPeter Wemm while (j--) { 6950e3d5408SPeter Wemm if (infodump) 6960e3d5408SPeter Wemm (void) putchar(fgetc(tmp_fp)); 6970e3d5408SPeter Wemm else 6980e3d5408SPeter Wemm put_translate(fgetc(tmp_fp)); 69915589c42SPeter Wemm } 7000e3d5408SPeter Wemm 7010e3d5408SPeter Wemm len = dump_entry(&qp->tterm, limited, numbers, NULL); 7020e3d5408SPeter Wemm for (j = 0; j < qp->nuses; j++) 70315589c42SPeter Wemm len += dump_uses(qp->uses[j].name, !capdump); 7040e3d5408SPeter Wemm (void) putchar('\n'); 7050e3d5408SPeter Wemm if (debug_level != 0 && !limited) 7060e3d5408SPeter Wemm printf("# length=%d\n", len); 7070e3d5408SPeter Wemm } 70815589c42SPeter Wemm } 7097a69bbfbSPeter Wemm if (!namelst && _nc_tail) { 7100e3d5408SPeter Wemm int c, oldc = '\0'; 7110e3d5408SPeter Wemm bool in_comment = FALSE; 7120e3d5408SPeter Wemm bool trailing_comment = FALSE; 7130e3d5408SPeter Wemm 7140e3d5408SPeter Wemm (void) fseek(tmp_fp, _nc_tail->cend, SEEK_SET); 71515589c42SPeter Wemm while ((c = fgetc(tmp_fp)) != EOF) { 7160e3d5408SPeter Wemm if (oldc == '\n') { 7170e3d5408SPeter Wemm if (c == '#') { 7180e3d5408SPeter Wemm trailing_comment = TRUE; 7190e3d5408SPeter Wemm in_comment = TRUE; 7200e3d5408SPeter Wemm } else { 7210e3d5408SPeter Wemm in_comment = FALSE; 7220e3d5408SPeter Wemm } 7230e3d5408SPeter Wemm } 7240e3d5408SPeter Wemm if (trailing_comment 7250e3d5408SPeter Wemm && (in_comment || (oldc == '\n' && c == '\n'))) 7260e3d5408SPeter Wemm putchar(c); 7270e3d5408SPeter Wemm oldc = c; 7280e3d5408SPeter Wemm } 7290e3d5408SPeter Wemm } 7300e3d5408SPeter Wemm } 7310e3d5408SPeter Wemm } 7320e3d5408SPeter Wemm 7330e3d5408SPeter Wemm /* Show the directory into which entries were written, and the total 7340e3d5408SPeter Wemm * number of entries 7350e3d5408SPeter Wemm */ 7360e3d5408SPeter Wemm if (showsummary 7370e3d5408SPeter Wemm && (!(check_only || infodump || capdump))) { 7380e3d5408SPeter Wemm int total = _nc_tic_written(); 7390e3d5408SPeter Wemm if (total != 0) 7400e3d5408SPeter Wemm fprintf(log_fp, "%d entries written to %s\n", 7410e3d5408SPeter Wemm total, 7420e3d5408SPeter Wemm _nc_tic_dir((char *) 0)); 7430e3d5408SPeter Wemm else 7440e3d5408SPeter Wemm fprintf(log_fp, "No entries written\n"); 7450e3d5408SPeter Wemm } 7460e3d5408SPeter Wemm cleanup(); 7470e3d5408SPeter Wemm return (EXIT_SUCCESS); 7480e3d5408SPeter Wemm } 7490e3d5408SPeter Wemm 7500e3d5408SPeter Wemm /* 7510e3d5408SPeter Wemm * This bit of legerdemain turns all the terminfo variable names into 7520e3d5408SPeter Wemm * references to locations in the arrays Booleans, Numbers, and Strings --- 7530e3d5408SPeter Wemm * precisely what's needed (see comp_parse.c). 7540e3d5408SPeter Wemm */ 7550e3d5408SPeter Wemm 7560e3d5408SPeter Wemm TERMINAL *cur_term; /* tweak to avoid linking lib_cur_term.c */ 7570e3d5408SPeter Wemm 7580e3d5408SPeter Wemm #undef CUR 7590e3d5408SPeter Wemm #define CUR tp-> 7600e3d5408SPeter Wemm 76115589c42SPeter Wemm /* 76218259542SPeter Wemm * Returns the expected number of parameters for the given capability. 76318259542SPeter Wemm */ 76418259542SPeter Wemm static int 7657a69bbfbSPeter Wemm expected_params(const char *name) 76618259542SPeter Wemm { 76718259542SPeter Wemm /* *INDENT-OFF* */ 76818259542SPeter Wemm static const struct { 76918259542SPeter Wemm const char *name; 77018259542SPeter Wemm int count; 77118259542SPeter Wemm } table[] = { 7727a69bbfbSPeter Wemm { "S0", 1 }, /* 'screen' extension */ 77318259542SPeter Wemm { "birep", 2 }, 77418259542SPeter Wemm { "chr", 1 }, 77518259542SPeter Wemm { "colornm", 1 }, 77618259542SPeter Wemm { "cpi", 1 }, 7777a69bbfbSPeter Wemm { "csnm", 1 }, 77818259542SPeter Wemm { "csr", 2 }, 77918259542SPeter Wemm { "cub", 1 }, 78018259542SPeter Wemm { "cud", 1 }, 78118259542SPeter Wemm { "cuf", 1 }, 78218259542SPeter Wemm { "cup", 2 }, 78318259542SPeter Wemm { "cuu", 1 }, 7847a69bbfbSPeter Wemm { "cvr", 1 }, 78518259542SPeter Wemm { "cwin", 5 }, 78618259542SPeter Wemm { "dch", 1 }, 7877a69bbfbSPeter Wemm { "defc", 3 }, 78818259542SPeter Wemm { "dial", 1 }, 78918259542SPeter Wemm { "dispc", 1 }, 79018259542SPeter Wemm { "dl", 1 }, 79118259542SPeter Wemm { "ech", 1 }, 79218259542SPeter Wemm { "getm", 1 }, 79318259542SPeter Wemm { "hpa", 1 }, 79418259542SPeter Wemm { "ich", 1 }, 79518259542SPeter Wemm { "il", 1 }, 79618259542SPeter Wemm { "indn", 1 }, 79718259542SPeter Wemm { "initc", 4 }, 79818259542SPeter Wemm { "initp", 7 }, 79918259542SPeter Wemm { "lpi", 1 }, 80018259542SPeter Wemm { "mc5p", 1 }, 80118259542SPeter Wemm { "mrcup", 2 }, 80218259542SPeter Wemm { "mvpa", 1 }, 80318259542SPeter Wemm { "pfkey", 2 }, 80418259542SPeter Wemm { "pfloc", 2 }, 80518259542SPeter Wemm { "pfx", 2 }, 80618259542SPeter Wemm { "pfxl", 3 }, 80718259542SPeter Wemm { "pln", 2 }, 80818259542SPeter Wemm { "qdial", 1 }, 8097a69bbfbSPeter Wemm { "rcsd", 1 }, 81018259542SPeter Wemm { "rep", 2 }, 81118259542SPeter Wemm { "rin", 1 }, 81218259542SPeter Wemm { "sclk", 3 }, 81318259542SPeter Wemm { "scp", 1 }, 81418259542SPeter Wemm { "scs", 1 }, 8157a69bbfbSPeter Wemm { "scsd", 2 }, 81618259542SPeter Wemm { "setab", 1 }, 81718259542SPeter Wemm { "setaf", 1 }, 81818259542SPeter Wemm { "setb", 1 }, 81918259542SPeter Wemm { "setcolor", 1 }, 82018259542SPeter Wemm { "setf", 1 }, 82118259542SPeter Wemm { "sgr", 9 }, 82218259542SPeter Wemm { "sgr1", 6 }, 82318259542SPeter Wemm { "slength", 1 }, 82418259542SPeter Wemm { "slines", 1 }, 82518259542SPeter Wemm { "smgbp", 2 }, 82618259542SPeter Wemm { "smglp", 2 }, 82718259542SPeter Wemm { "smglr", 2 }, 82818259542SPeter Wemm { "smgrp", 1 }, 82918259542SPeter Wemm { "smgtb", 2 }, 8307a69bbfbSPeter Wemm { "smgtp", 1 }, 83118259542SPeter Wemm { "tsl", 1 }, 83218259542SPeter Wemm { "u6", -1 }, 83318259542SPeter Wemm { "vpa", 1 }, 83418259542SPeter Wemm { "wind", 4 }, 83518259542SPeter Wemm { "wingo", 1 }, 83618259542SPeter Wemm }; 83718259542SPeter Wemm /* *INDENT-ON* */ 83818259542SPeter Wemm 83918259542SPeter Wemm unsigned n; 84018259542SPeter Wemm int result = 0; /* function-keys, etc., use none */ 84118259542SPeter Wemm 84218259542SPeter Wemm for (n = 0; n < SIZEOF(table); n++) { 84318259542SPeter Wemm if (!strcmp(name, table[n].name)) { 84418259542SPeter Wemm result = table[n].count; 84518259542SPeter Wemm break; 84618259542SPeter Wemm } 84718259542SPeter Wemm } 84818259542SPeter Wemm 84918259542SPeter Wemm return result; 85018259542SPeter Wemm } 85118259542SPeter Wemm 85218259542SPeter Wemm /* 85318259542SPeter Wemm * Make a quick sanity check for the parameters which are used in the given 85418259542SPeter Wemm * strings. If there are no "%p" tokens, then there should be no other "%" 85518259542SPeter Wemm * markers. 85618259542SPeter Wemm */ 85718259542SPeter Wemm static void 8587a69bbfbSPeter Wemm check_params(TERMTYPE * tp, const char *name, char *value) 85918259542SPeter Wemm { 86018259542SPeter Wemm int expected = expected_params(name); 86118259542SPeter Wemm int actual = 0; 86218259542SPeter Wemm int n; 86318259542SPeter Wemm bool params[10]; 86418259542SPeter Wemm char *s = value; 86518259542SPeter Wemm 86618259542SPeter Wemm for (n = 0; n < 10; n++) 86718259542SPeter Wemm params[n] = FALSE; 86818259542SPeter Wemm 86918259542SPeter Wemm while (*s != 0) { 87018259542SPeter Wemm if (*s == '%') { 87118259542SPeter Wemm if (*++s == '\0') { 87218259542SPeter Wemm _nc_warning("expected character after %% in %s", name); 87318259542SPeter Wemm break; 87418259542SPeter Wemm } else if (*s == 'p') { 87518259542SPeter Wemm if (*++s == '\0' || !isdigit((int) *s)) { 87618259542SPeter Wemm _nc_warning("expected digit after %%p in %s", name); 87718259542SPeter Wemm return; 87818259542SPeter Wemm } else { 87918259542SPeter Wemm n = (*s - '0'); 88018259542SPeter Wemm if (n > actual) 88118259542SPeter Wemm actual = n; 88218259542SPeter Wemm params[n] = TRUE; 88318259542SPeter Wemm } 88418259542SPeter Wemm } 88518259542SPeter Wemm } 88618259542SPeter Wemm s++; 88718259542SPeter Wemm } 88818259542SPeter Wemm 88918259542SPeter Wemm if (params[0]) { 89018259542SPeter Wemm _nc_warning("%s refers to parameter 0 (%%p0), which is not allowed", name); 89118259542SPeter Wemm } 89218259542SPeter Wemm if (value == set_attributes || expected < 0) { 89318259542SPeter Wemm ; 89418259542SPeter Wemm } else if (expected != actual) { 89518259542SPeter Wemm _nc_warning("%s uses %d parameters, expected %d", name, 89618259542SPeter Wemm actual, expected); 89718259542SPeter Wemm for (n = 1; n < actual; n++) { 89818259542SPeter Wemm if (!params[n]) 89918259542SPeter Wemm _nc_warning("%s omits parameter %d", name, n); 90018259542SPeter Wemm } 90118259542SPeter Wemm } 90218259542SPeter Wemm } 90318259542SPeter Wemm 90418259542SPeter Wemm /* 90515589c42SPeter Wemm * An sgr string may contain several settings other than the one we're 90615589c42SPeter Wemm * interested in, essentially sgr0 + rmacs + whatever. As long as the 90715589c42SPeter Wemm * "whatever" is contained in the sgr string, that is close enough for our 90815589c42SPeter Wemm * sanity check. 90915589c42SPeter Wemm */ 91015589c42SPeter Wemm static bool 91115589c42SPeter Wemm similar_sgr(char *a, char *b) 91215589c42SPeter Wemm { 91315589c42SPeter Wemm while (*b != 0) { 91415589c42SPeter Wemm while (*a != *b) { 9157a69bbfbSPeter Wemm if (*a == 0) { 9167a69bbfbSPeter Wemm if (b[0] == '$' 9177a69bbfbSPeter Wemm && b[1] == '<') { 9187a69bbfbSPeter Wemm _nc_warning("Did not find delay %s", _nc_visbuf(b)); 9197a69bbfbSPeter Wemm } else { 9207a69bbfbSPeter Wemm _nc_warning("Unmatched portion %s", _nc_visbuf(b)); 9217a69bbfbSPeter Wemm } 92215589c42SPeter Wemm return FALSE; 9237a69bbfbSPeter Wemm } 92415589c42SPeter Wemm a++; 92515589c42SPeter Wemm } 92615589c42SPeter Wemm a++; 92715589c42SPeter Wemm b++; 92815589c42SPeter Wemm } 92915589c42SPeter Wemm return TRUE; 93015589c42SPeter Wemm } 93115589c42SPeter Wemm 93215589c42SPeter Wemm static void 93315589c42SPeter Wemm check_sgr(TERMTYPE * tp, char *zero, int num, char *cap, const char *name) 93415589c42SPeter Wemm { 93515589c42SPeter Wemm char *test = tparm(set_attributes, 93615589c42SPeter Wemm num == 1, 93715589c42SPeter Wemm num == 2, 93815589c42SPeter Wemm num == 3, 93915589c42SPeter Wemm num == 4, 94015589c42SPeter Wemm num == 5, 94115589c42SPeter Wemm num == 6, 94215589c42SPeter Wemm num == 7, 94315589c42SPeter Wemm num == 8, 94415589c42SPeter Wemm num == 9); 9457a69bbfbSPeter Wemm tparm_errs += _nc_tparm_err; 94615589c42SPeter Wemm if (test != 0) { 94715589c42SPeter Wemm if (PRESENT(cap)) { 94815589c42SPeter Wemm if (!similar_sgr(test, cap)) { 94915589c42SPeter Wemm _nc_warning("%s differs from sgr(%d): %s", name, num, 95015589c42SPeter Wemm _nc_visbuf(test)); 95115589c42SPeter Wemm } 95215589c42SPeter Wemm } else if (strcmp(test, zero)) { 95315589c42SPeter Wemm _nc_warning("sgr(%d) present, but not %s", num, name); 95415589c42SPeter Wemm } 95515589c42SPeter Wemm } else if (PRESENT(cap)) { 95615589c42SPeter Wemm _nc_warning("sgr(%d) missing, but %s present", num, name); 95715589c42SPeter Wemm } 95815589c42SPeter Wemm } 95915589c42SPeter Wemm 96015589c42SPeter Wemm #define CHECK_SGR(num,name) check_sgr(tp, zero, num, name, #name) 96115589c42SPeter Wemm 9620e3d5408SPeter Wemm /* other sanity-checks (things that we don't want in the normal 9630e3d5408SPeter Wemm * logic that reads a terminfo entry) 9640e3d5408SPeter Wemm */ 96515589c42SPeter Wemm static void 96615589c42SPeter Wemm check_termtype(TERMTYPE * tp) 9670e3d5408SPeter Wemm { 9680e3d5408SPeter Wemm bool conflict = FALSE; 9690e3d5408SPeter Wemm unsigned j, k; 9700e3d5408SPeter Wemm char fkeys[STRCOUNT]; 9710e3d5408SPeter Wemm 9720e3d5408SPeter Wemm /* 9730e3d5408SPeter Wemm * A terminal entry may contain more than one keycode assigned to 9740e3d5408SPeter Wemm * a given string (e.g., KEY_END and KEY_LL). But curses will only 9750e3d5408SPeter Wemm * return one (the last one assigned). 9760e3d5408SPeter Wemm */ 9770e3d5408SPeter Wemm memset(fkeys, 0, sizeof(fkeys)); 9780e3d5408SPeter Wemm for (j = 0; _nc_tinfo_fkeys[j].code; j++) { 9790e3d5408SPeter Wemm char *a = tp->Strings[_nc_tinfo_fkeys[j].offset]; 9800e3d5408SPeter Wemm bool first = TRUE; 9810e3d5408SPeter Wemm if (!VALID_STRING(a)) 9820e3d5408SPeter Wemm continue; 9830e3d5408SPeter Wemm for (k = j + 1; _nc_tinfo_fkeys[k].code; k++) { 9840e3d5408SPeter Wemm char *b = tp->Strings[_nc_tinfo_fkeys[k].offset]; 9850e3d5408SPeter Wemm if (!VALID_STRING(b) 9860e3d5408SPeter Wemm || fkeys[k]) 9870e3d5408SPeter Wemm continue; 9880e3d5408SPeter Wemm if (!strcmp(a, b)) { 9890e3d5408SPeter Wemm fkeys[j] = 1; 9900e3d5408SPeter Wemm fkeys[k] = 1; 9910e3d5408SPeter Wemm if (first) { 9920e3d5408SPeter Wemm if (!conflict) { 9930e3d5408SPeter Wemm _nc_warning("Conflicting key definitions (using the last)"); 9940e3d5408SPeter Wemm conflict = TRUE; 9950e3d5408SPeter Wemm } 9960e3d5408SPeter Wemm fprintf(stderr, "... %s is the same as %s", 9970e3d5408SPeter Wemm keyname(_nc_tinfo_fkeys[j].code), 9980e3d5408SPeter Wemm keyname(_nc_tinfo_fkeys[k].code)); 9990e3d5408SPeter Wemm first = FALSE; 10000e3d5408SPeter Wemm } else { 10010e3d5408SPeter Wemm fprintf(stderr, ", %s", 10020e3d5408SPeter Wemm keyname(_nc_tinfo_fkeys[k].code)); 10030e3d5408SPeter Wemm } 10040e3d5408SPeter Wemm } 10050e3d5408SPeter Wemm } 10060e3d5408SPeter Wemm if (!first) 10070e3d5408SPeter Wemm fprintf(stderr, "\n"); 10080e3d5408SPeter Wemm } 10090e3d5408SPeter Wemm 101018259542SPeter Wemm for (j = 0; j < NUM_STRINGS(tp); j++) { 101118259542SPeter Wemm char *a = tp->Strings[j]; 101218259542SPeter Wemm if (VALID_STRING(a)) 101318259542SPeter Wemm check_params(tp, ExtStrname(tp, j, strnames), a); 101418259542SPeter Wemm } 101518259542SPeter Wemm 10160e3d5408SPeter Wemm /* 10170e3d5408SPeter Wemm * Quick check for color. We could also check if the ANSI versus 10180e3d5408SPeter Wemm * non-ANSI strings are misused. 10190e3d5408SPeter Wemm */ 10200e3d5408SPeter Wemm if ((max_colors > 0) != (max_pairs > 0) 10210e3d5408SPeter Wemm || (max_colors > max_pairs)) 10220e3d5408SPeter Wemm _nc_warning("inconsistent values for max_colors and max_pairs"); 10230e3d5408SPeter Wemm 102415589c42SPeter Wemm PAIRED(set_foreground, set_background); 102515589c42SPeter Wemm PAIRED(set_a_foreground, set_a_background); 10260e3d5408SPeter Wemm 10270e3d5408SPeter Wemm /* 10280e3d5408SPeter Wemm * These may be mismatched because the terminal description relies on 10290e3d5408SPeter Wemm * restoring the cursor visibility by resetting it. 10300e3d5408SPeter Wemm */ 103115589c42SPeter Wemm ANDMISSING(cursor_invisible, cursor_normal); 103215589c42SPeter Wemm ANDMISSING(cursor_visible, cursor_normal); 103315589c42SPeter Wemm 103415589c42SPeter Wemm if (PRESENT(cursor_visible) && PRESENT(cursor_normal) 103515589c42SPeter Wemm && !strcmp(cursor_visible, cursor_normal)) 103615589c42SPeter Wemm _nc_warning("cursor_visible is same as cursor_normal"); 10370e3d5408SPeter Wemm 10380e3d5408SPeter Wemm /* 10390e3d5408SPeter Wemm * From XSI & O'Reilly, we gather that sc/rc are required if csr is 10400e3d5408SPeter Wemm * given, because the cursor position after the scrolling operation is 10410e3d5408SPeter Wemm * performed is undefined. 10420e3d5408SPeter Wemm */ 104315589c42SPeter Wemm ANDMISSING(change_scroll_region, save_cursor); 104415589c42SPeter Wemm ANDMISSING(change_scroll_region, restore_cursor); 104515589c42SPeter Wemm 10467a69bbfbSPeter Wemm tparm_errs = 0; 104715589c42SPeter Wemm if (PRESENT(set_attributes)) { 104815589c42SPeter Wemm char *zero = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, 0); 104915589c42SPeter Wemm 105015589c42SPeter Wemm zero = strdup(zero); 105115589c42SPeter Wemm CHECK_SGR(1, enter_standout_mode); 105215589c42SPeter Wemm CHECK_SGR(2, enter_underline_mode); 105315589c42SPeter Wemm CHECK_SGR(3, enter_reverse_mode); 105415589c42SPeter Wemm CHECK_SGR(4, enter_blink_mode); 105515589c42SPeter Wemm CHECK_SGR(5, enter_dim_mode); 105615589c42SPeter Wemm CHECK_SGR(6, enter_bold_mode); 105715589c42SPeter Wemm CHECK_SGR(7, enter_secure_mode); 105815589c42SPeter Wemm CHECK_SGR(8, enter_protected_mode); 105915589c42SPeter Wemm CHECK_SGR(9, enter_alt_charset_mode); 106015589c42SPeter Wemm free(zero); 10617a69bbfbSPeter Wemm if (tparm_errs) 10627a69bbfbSPeter Wemm _nc_warning("stack error in sgr string"); 106315589c42SPeter Wemm } 10640e3d5408SPeter Wemm 10650e3d5408SPeter Wemm /* 10660e3d5408SPeter Wemm * Some standard applications (e.g., vi) and some non-curses 10670e3d5408SPeter Wemm * applications (e.g., jove) get confused if we have both ich/ich1 and 10680e3d5408SPeter Wemm * smir/rmir. Let's be nice and warn about that, too, even though 10690e3d5408SPeter Wemm * ncurses handles it. 10700e3d5408SPeter Wemm */ 10710e3d5408SPeter Wemm if ((PRESENT(enter_insert_mode) || PRESENT(exit_insert_mode)) 10720e3d5408SPeter Wemm && (PRESENT(insert_character) || PRESENT(parm_ich))) { 10730e3d5408SPeter Wemm _nc_warning("non-curses applications may be confused by ich/ich1 with smir/rmir"); 10740e3d5408SPeter Wemm } 10750e3d5408SPeter Wemm 10760e3d5408SPeter Wemm /* 10770e3d5408SPeter Wemm * Finally, do the non-verbose checks 10780e3d5408SPeter Wemm */ 10790e3d5408SPeter Wemm if (save_check_termtype != 0) 10800e3d5408SPeter Wemm save_check_termtype(tp); 10810e3d5408SPeter Wemm } 1082