-
-/***************************************************************************
-* COPYRIGHT NOTICE *
-****************************************************************************
-* ncurses is copyright (C) 1992-1995 *
-* Zeyd M. Ben-Halim *
-* zmbenhal@netcom.com *
-* Eric S. Raymond *
-* esr@snark.thyrsus.com *
-* *
-* Permission is hereby granted to reproduce and distribute ncurses *
-* by any means and for any fee, whether alone or as part of a *
-* larger distribution, in source or in binary form, PROVIDED *
-* this notice is included with any such distribution, and is not *
-* removed from any of its header files. Mention of ncurses in any *
-* applications linked with it is highly appreciated. *
-* *
-* ncurses comes AS IS with no warranty, implied or expressed. *
-* *
-***************************************************************************/
+/****************************************************************************
+ * Copyright (c) 1998,1999 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), to deal in the Software without restriction, including *
+ * without limitation the rights to use, copy, modify, merge, publish, *
+ * distribute, distribute with modifications, sublicense, and/or sell *
+ * copies of the Software, and to permit persons to whom the Software is *
+ * furnished to do so, subject to the following conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included *
+ * in all copies or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+ * *
+ * Except as contained in this notice, the name(s) of the above copyright *
+ * holders shall not be used in advertising or otherwise to promote the *
+ * sale, use or other dealings in this Software without prior written *
+ * authorization. *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ ****************************************************************************/
/*
#include <progs.priv.h>
-#include <ctype.h>
-
#include <term_entry.h>
#include <dump_entry.h>
-MODULE_ID("$Id: infocmp.c,v 1.27 1997/02/15 18:54:44 tom Exp $")
+MODULE_ID("$Id: infocmp.c,v 1.44 1999/06/16 00:39:48 tom Exp $")
#define L_CURL "{"
#define R_CURL "}"
-#define VALID_STRING(s) ((s) != CANCELLED_STRING && (s) != ABSENT_STRING)
-
#define MAXTERMS 32 /* max # terminal arguments we can handle */
const char *_nc_progname = "infocmp";
static int termcount; /* count of terminal entries */
static const char *tversion; /* terminfo version selected */
+static int numbers = 0; /* format "%'char'" to/from "%{number}" */
static int outform; /* output format */
static int sortmode; /* sort_mode */
static int itrace; /* trace flag for debugging */
static void ExitProgram(int code)
{
while (termcount-- > 0)
- _nc_free_termtype(&term[termcount], FALSE);
+ _nc_free_termtype(&term[termcount]);
_nc_leaks_dump_entry();
_nc_free_and_exit(code);
}
if (usestr == ABSENT_STRING && termstr == ABSENT_STRING)
return(FAIL);
- else if (!usestr || !termstr || capcmp(usestr,termstr))
+ else if (!usestr || !termstr || capcmp(usestr, termstr))
return(TRUE);
else
return(FAIL);
{
int i;
- for (i = 0; i < BOOLCOUNT; i++)
+ for (i = 0; i < NUM_BOOLEANS(t1); i++)
if (t1->Booleans[i] != t2->Booleans[i])
return(FALSE);
- for (i = 0; i < NUMCOUNT; i++)
+ for (i = 0; i < NUM_NUMBERS(t1); i++)
if (t1->Numbers[i] != t2->Numbers[i])
return(FALSE);
- for (i = 0; i < STRCOUNT; i++)
+ for (i = 0; i < NUM_STRINGS(t1); i++)
if (capcmp(t1->Strings[i], t2->Strings[i]))
return(FALSE);
return(TRUE);
}
+#define TIC_EXPAND(result) _nc_tic_expand(result, outform==F_TERMINFO, numbers)
+
static void compare_predicate(int type, int idx, const char *name)
/* predicate function to use for entry difference reports */
{
else
{
(void) strcpy(buf1, "'");
- (void) strcat(buf1, expand(s1));
+ (void) strcat(buf1, TIC_EXPAND(s1));
(void) strcat(buf1, "'");
}
else
{
(void) strcpy(buf2, "'");
- (void) strcat(buf2, expand(s2));
+ (void) strcat(buf2, TIC_EXPAND(s2));
(void) strcat(buf2, "'");
}
- (void) printf("\t%s: %s, %s.\n",
- name, buf1, buf2);
+ if (strcmp(buf1, buf2))
+ (void) printf("\t%s: %s, %s.\n",
+ name, buf1, buf2);
}
break;
case C_COMMON:
if (s1 && s2 && !capcmp(s1, s2))
- (void) printf("\t%s= '%s'.\n",name,expand(s1));
+ (void) printf("\t%s= '%s'.\n", name, TIC_EXPAND(s1));
break;
case C_NAND:
/* couldn't match anything */
buf2[0] = *sp;
buf2[1] = '\0';
- (void) strcat(buf, expand(buf2));
+ (void) strcat(buf, TIC_EXPAND(buf2));
}
}
(void) printf("%s\n", buf);
ENTRY *qp, *rp;
int i, n;
- dump_init((char *)NULL, F_LITERAL, S_TERMINFO, 0, itrace);
+ dump_init((char *)NULL, F_LITERAL, S_TERMINFO, 0, itrace, FALSE);
for (n = 0; n < argc && n < MAXCOMPARE; n++)
{
_nc_read_entry_source(stdin, NULL, TRUE, FALSE, NULLHOOK);
if (itrace)
- (void) fprintf(stderr, "Resolving file %d...\n",n-0);
+ (void) fprintf(stderr, "Resolving file %d...\n", n-0);
/* do use resolution */
if (!_nc_resolve_uses())
for (qp = heads[0]; qp; qp = qp->next)
{
for (rp = heads[1]; rp; rp = rp->next)
- if (_nc_entry_match(qp->tterm.term_names,rp->tterm.term_names))
+ if (_nc_entry_match(qp->tterm.term_names, rp->tterm.term_names))
{
/*
* This is why the uses structure parent element is
{
rp = (ENTRY *)qp->uses[0].parent;
+#if NCURSES_XNAMES
+ if (termcount > 1)
+ _nc_align_termtype(&qp->tterm, &rp->tterm);
+#endif
if (qp->nuses == 1 && !entryeq(&qp->tterm, &rp->tterm))
{
char name1[NAMESIZE], name2[NAMESIZE];
- memcpy(&term[0], &qp->tterm, sizeof(TERMTYPE));
- memcpy(&term[1], &rp->tterm, sizeof(TERMTYPE));
+ term[0] = qp->tterm;
+ term[1] = rp->tterm;
(void) canonical_name(qp->tterm.term_names, name1);
(void) canonical_name(rp->tterm.term_names, name2);
{
case C_DIFFERENCE:
if (itrace)
- (void)fprintf(stderr,"infocmp: dumping differences\n");
+ (void)fprintf(stderr, "infocmp: dumping differences\n");
(void) printf("comparing %s to %s.\n", name1, name2);
- compare_entry(compare_predicate);
+ compare_entry(compare_predicate, term);
break;
case C_COMMON:
(void) fprintf(stderr,
"infocmp: dumping common capabilities\n");
(void) printf("comparing %s to %s.\n", name1, name2);
- compare_entry(compare_predicate);
+ compare_entry(compare_predicate, term);
break;
case C_NAND:
(void) fprintf(stderr,
"infocmp: dumping differences\n");
(void) printf("comparing %s to %s.\n", name1, name2);
- compare_entry(compare_predicate);
+ compare_entry(compare_predicate, term);
break;
}
static void usage(void)
{
- fprintf(stderr,
-"usage: infocmp [-dcnILCuvV1T] [-s d| i| l| c] [-w width] [-A directory] [-B directory] [termname...]\n");
+ static const char *tbl[] = {
+ "Usage: infocmp [options] [-A directory] [-B directory] [termname...]"
+ ,""
+ ,"Options:"
+ ," -1 print single-column"
+ ," -C use termcap-names"
+ ," -F compare terminfo-files"
+ ," -I use terminfo-names"
+ ," -L use long names"
+ ," -R subset (see manpage)"
+ ," -T eliminate size limits (test)"
+ ," -V print version"
+ ," -c list common capabilities"
+ ," -d list different capabilities"
+ ," -e format output for C initializer"
+ ," -E format output as C tables"
+ ," -f with -1, format complex strings"
+ ," -G format %{number} to %'char'"
+ ," -g format %'char' to %{number}"
+ ," -i analyze initialization/reset"
+ ," -l output terminfo names"
+ ," -n list capabilities in neither"
+ ," -p ignore padding specifiers"
+ ," -r with -C, output in termcap form"
+ ," -s [d|i|l|c] sort fields"
+ ," -u produce source with 'use='"
+ ," -v number (verbose)"
+ ," -w number (width)"
+ };
+ const size_t first = 3;
+ const size_t last = sizeof(tbl)/sizeof(tbl[0]);
+ const size_t left = (last - first + 1) / 2 + first;
+ size_t n;
+
+ for (n = 0; n < left; n++) {
+ size_t m = (n < first) ? last : n + left - first;
+ if (m < last)
+ fprintf(stderr, "%-40.40s%s\n", tbl[n], tbl[m]);
+ else
+ fprintf(stderr, "%s\n", tbl[n]);
+ }
exit(EXIT_FAILURE);
}
+static char * name_initializer(const char *type)
+{
+ static char *initializer;
+ char *s;
+
+ if (initializer == 0)
+ initializer = malloc(strlen(term->term_names) + 20);
+
+ (void) sprintf(initializer, "%s_data_%s", type, term->term_names);
+ for (s = initializer; *s != 0 && *s != '|'; s++)
+ {
+ if (!isalnum(*s))
+ *s = '_';
+ }
+ *s = 0;
+ return initializer;
+}
+
+/* dump C initializers for the terminal type */
+static void dump_initializers(void)
+{
+ int n;
+ const char *str = 0;
+ int size;
+
+ (void) printf("static bool %s[] = %s\n", name_initializer("bool"), L_CURL);
+
+ for_each_boolean(n,term)
+ {
+ switch((int)(term->Booleans[n]))
+ {
+ case TRUE:
+ str = "TRUE";
+ break;
+
+ case FALSE:
+ str = "FALSE";
+ break;
+
+ case ABSENT_BOOLEAN:
+ str = "ABSENT_BOOLEAN";
+ break;
+
+ case CANCELLED_BOOLEAN:
+ str = "CANCELLED_BOOLEAN";
+ break;
+ }
+ (void) printf("\t/* %3d: %-8s */\t%s,\n",
+ n, ExtBoolname(term,n,boolnames), str);
+ }
+ (void) printf("%s;\n", R_CURL);
+
+ (void) printf("static short %s[] = %s\n", name_initializer("number"), L_CURL);
+
+ for_each_number(n,term)
+ {
+ char buf[BUFSIZ];
+ switch (term->Numbers[n])
+ {
+ case ABSENT_NUMERIC:
+ str = "ABSENT_NUMERIC";
+ break;
+ case CANCELLED_NUMERIC:
+ str = "CANCELLED_NUMERIC";
+ break;
+ default:
+ sprintf(buf, "%d", term->Numbers[n]);
+ str = buf;
+ break;
+ }
+ (void) printf("\t/* %3d: %-8s */\t%s,\n", n, ExtNumname(term,n,numnames), str);
+ }
+ (void) printf("%s;\n", R_CURL);
+
+ size = sizeof(TERMTYPE)
+ + (NUM_BOOLEANS(term) * sizeof(term->Booleans[0]))
+ + (NUM_NUMBERS(term) * sizeof(term->Numbers[0]));
+
+ (void) printf("static char * %s[] = %s\n", name_initializer("string"), L_CURL);
+
+ for_each_string(n,term)
+ {
+ char buf[BUFSIZ], *sp, *tp;
+
+ if (term->Strings[n] == ABSENT_STRING)
+ str = "ABSENT_STRING";
+ else if (term->Strings[n] == CANCELLED_STRING)
+ str = "CANCELLED_STRING";
+ else
+ {
+ tp = buf;
+ *tp++ = '"';
+ for (sp = term->Strings[n]; *sp; sp++)
+ {
+ if (isascii(*sp) && isprint(*sp) && *sp !='\\' && *sp != '"')
+ *tp++ = *sp;
+ else
+ {
+ (void) sprintf(tp, "\\%03o", *sp & 0xff);
+ tp += 4;
+ }
+ }
+ *tp++ = '"';
+ *tp = '\0';
+ size += (strlen(term->Strings[n]) + 1);
+ str = buf;
+ }
+#if NCURSES_XNAMES
+ if (n == STRCOUNT)
+ {
+ (void) printf("%s;\n", R_CURL);
+
+ (void) printf("static char * %s[] = %s\n", name_initializer("string_ext"), L_CURL);
+ }
+#endif
+ (void) printf("\t/* %3d: %-8s */\t%s,\n", n, ExtStrname(term,n,strnames), str);
+ }
+ (void) printf("%s;\n", R_CURL);
+}
+
+/* dump C initializers for the terminal type */
+static void dump_termtype(void)
+{
+ (void) printf("\t%s\n\t\t\"%s\",\n", L_CURL, term->term_names);
+ (void) printf("\t\t(char *)0,\t/* pointer to string table */\n");
+
+ (void) printf("\t\t%s,\n", name_initializer("bool"));
+ (void) printf("\t\t%s,\n", name_initializer("number"));
+
+ (void) printf("\t\t%s,\n", name_initializer("string"));
+
+#if NCURSES_XNAMES
+ (void) printf("#if NCURSES_XNAMES\n");
+ (void) printf("\t\t(char *)0,\t/* pointer to extended string table */\n");
+ (void) printf("\t\t%s,\t/* ...corresponding names */\n",
+ (NUM_STRINGS(term) != STRCOUNT)
+ ? name_initializer("string_ext")
+ : "(char **)0");
+
+ (void) printf("\t\t%d,\t\t/* count total Booleans */\n", NUM_BOOLEANS(term));
+ (void) printf("\t\t%d,\t\t/* count total Numbers */\n", NUM_NUMBERS(term));
+ (void) printf("\t\t%d,\t\t/* count total Strings */\n", NUM_STRINGS(term));
+
+ (void) printf("\t\t%d,\t\t/* count extensions to Booleans */\n", NUM_BOOLEANS(term) - BOOLCOUNT);
+ (void) printf("\t\t%d,\t\t/* count extensions to Numbers */\n", NUM_NUMBERS(term) - NUMCOUNT);
+ (void) printf("\t\t%d,\t\t/* count extensions to Strings */\n", NUM_STRINGS(term) - STRCOUNT);
+
+ (void) printf("#endif /* NCURSES_XNAMES */\n");
+#endif /* NCURSES_XNAMES */
+ (void) printf("\t%s\n", R_CURL);
+}
+
/***************************************************************************
*
* Main sequence
int main(int argc, char *argv[])
{
char *terminal, *firstdir, *restdir;
- path tfile[MAXTERMS];
+ /* Avoid "local data >32k" error with mwcc */
+ /* Also avoid overflowing smaller stacks on systems like AmigaOS */
+ path *tfile = malloc(sizeof(path)*MAXTERMS);
int c, i, len;
+ bool formatted = FALSE;
bool filecompare = FALSE;
- bool initdump = FALSE;
+ int initdump = 0;
bool init_analyze = FALSE;
bool limited = TRUE;
/* where is the terminfo database location going to default to? */
restdir = firstdir = 0;
- while ((c = getopt(argc, argv, "decCFIinlLprR:s:uv:Vw:A:B:1T")) != EOF)
+ while ((c = getopt(argc, argv, "deEcCfFGgIinlLprR:s:uv:Vw:A:B:1T")) != EOF)
switch (c)
{
case 'd':
break;
case 'e':
- initdump = TRUE;
+ initdump |= 1;
+ break;
+
+ case 'E':
+ initdump |= 2;
break;
case 'c':
sortmode = S_TERMCAP;
break;
+ case 'f':
+ formatted = TRUE;
+ break;
+
+ case 'G':
+ numbers = 1;
+ break;
+
+ case 'g':
+ numbers = -1;
+ break;
+
case 'F':
filecompare = TRUE;
break;
+ case 'I':
+ outform = F_TERMINFO;
+ if (sortmode == S_DEFAULT)
+ sortmode = S_VARIABLE;
+ tversion = 0;
+ break;
+
case 'i':
init_analyze = TRUE;
break;
break;
case 'r':
- tversion = (char *)NULL;
+ tversion = 0;
+ limited = FALSE;
break;
case 'R':
case '1':
mwidth = 0;
break;
+
case 'T':
limited = FALSE;
break;
sortmode = S_TERMINFO;
/* set up for display */
- dump_init(tversion, outform, sortmode, mwidth, itrace);
+ dump_init(tversion, outform, sortmode, mwidth, itrace, formatted);
/* make sure we have at least one terminal name to work with */
if (optind >= argc)
}
}
+#if NCURSES_XNAMES
+ if (termcount > 1)
+ _nc_align_termtype(&term[0], &term[1]);
+#endif
+
/* dump as C initializer for the terminal type */
if (initdump)
{
- int n;
- const char *str = 0;
- int size;
-
- (void) printf("\t%s\n\t\t\"%s\",\n",
- L_CURL, term->term_names);
- (void) printf("\t\t(char *)0,\n");
-
- (void) printf("\t\t%s /* BOOLEANS */\n", L_CURL);
- for (n = 0; n < BOOLCOUNT; n++)
- {
- switch((int)(term->Booleans[n]))
- {
- case TRUE:
- str = "TRUE";
- break;
-
- case FALSE:
- str = "FALSE";
- break;
-
- case ABSENT_BOOLEAN:
- str = "ABSENT_BOOLEAN";
- break;
-
- case CANCELLED_BOOLEAN:
- str = "CANCELLED_BOOLEAN";
- break;
- }
- (void) printf("\t\t/* %s */\t%s%s,\n",
- boolnames[n], str,
- n == BOOLCOUNT-1 ? R_CURL : "");
- }
-
- (void) printf("\t\t%s /* NUMERICS */\n", L_CURL);
- for (n = 0; n < NUMCOUNT; n++)
- {
- char buf[BUFSIZ];
- switch (term->Numbers[n])
- {
- case ABSENT_NUMERIC:
- str = "ABSENT_NUMERIC";
- break;
- case CANCELLED_NUMERIC:
- str = "CANCELLED_NUMERIC";
- break;
- default:
- sprintf(buf, "%d", term->Numbers[n]);
- str = buf;
- break;
- }
- (void) printf("\t\t/* %s */\t%s%s,\n",
- numnames[n], str,
- n == NUMCOUNT-1 ? R_CURL : "");
- }
-
- size = sizeof(TERMTYPE)
- + (BOOLCOUNT * sizeof(term->Booleans[0]))
- + (NUMCOUNT * sizeof(term->Numbers[0]));
-
- (void) printf("\t\t%s /* STRINGS */\n", L_CURL);
- for (n = 0; n < STRCOUNT; n++)
- {
- char buf[BUFSIZ], *sp, *tp;
-
- if (term->Strings[n] == ABSENT_STRING)
- str = "ABSENT_STRING";
- else if (term->Strings[n] == CANCELLED_STRING)
- str = "CANCELLED_STRING";
- else
- {
- tp = buf;
- *tp++ = '"';
- for (sp = term->Strings[n]; *sp; sp++)
- if (isascii(*sp) && isprint(*sp) && *sp !='\\' && *sp != '"')
- *tp++ = *sp;
- else
- {
- (void) sprintf(tp, "\\%03o", *sp);
- tp += 4;
- }
- *tp++ = '"';
- *tp = '\0';
- size += (strlen(term->Strings[n]) + 1);
- str = buf;
- }
- (void) printf("\t\t/* %s */\t%s%s%s\n",
- strnames[n], str,
- n == STRCOUNT-1 ? R_CURL : "",
- n == STRCOUNT-1 ? "" : ",");
- }
- (void) printf("\t%s /* size = %d */\n", R_CURL, size);
+ if (initdump & 1)
+ dump_termtype();
+ if (initdump & 2)
+ dump_initializers();
ExitProgram(EXIT_SUCCESS);
}
tname[0]);
(void) printf("#\tReconstructed via infocmp from file: %s\n",
tfile[0]);
- len = dump_entry(&term[0], limited, NULL);
+ len = dump_entry(&term[0], limited, numbers, NULL);
putchar('\n');
if (itrace)
- (void)fprintf(stderr,"infocmp: length %d\n", len);
+ (void)fprintf(stderr, "infocmp: length %d\n", len);
break;
case C_DIFFERENCE:
if (itrace)
- (void)fprintf(stderr,"infocmp: dumping differences\n");
+ (void)fprintf(stderr, "infocmp: dumping differences\n");
(void) printf("comparing %s to %s.\n", tname[0], tname[1]);
- compare_entry(compare_predicate);
+ compare_entry(compare_predicate, term);
break;
case C_COMMON:
(void) fprintf(stderr,
"infocmp: dumping common capabilities\n");
(void) printf("comparing %s to %s.\n", tname[0], tname[1]);
- compare_entry(compare_predicate);
+ compare_entry(compare_predicate, term);
break;
case C_NAND:
(void) fprintf(stderr,
"infocmp: dumping differences\n");
(void) printf("comparing %s to %s.\n", tname[0], tname[1]);
- compare_entry(compare_predicate);
+ compare_entry(compare_predicate, term);
break;
case C_USEALL:
if (itrace)
(void) fprintf(stderr, "infocmp: dumping use entry\n");
- len = dump_entry(&term[0], limited, use_predicate);
+ len = dump_entry(&term[0], limited, numbers, use_predicate);
for (i = 1; i < termcount; i++)
len += dump_uses(tname[i], !(outform==F_TERMCAP || outform==F_TCONVERR));
putchar('\n');
if (itrace)
- (void)fprintf(stderr,"infocmp: length %d\n", len);
+ (void)fprintf(stderr, "infocmp: length %d\n", len);
break;
}
}