infocmp.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.13 */
/*
NAME
infocmp - compare terminfo descriptions, or dump a terminfo
description
AUTHOR
Tony Hansen, February 23, 1984.
*/
#include "curses.h"
#include "term.h"
#include "print.h"
#include <fcntl.h>
#include <stdlib.h>
/* externs from libcurses */
extern char *boolnames[];
extern char *boolcodes[];
extern char *boolfnames[];
extern char *numnames[];
extern char *numcodes[];
extern char *numfnames[];
extern char *strnames[];
extern char *strcodes[];
extern char *strfnames[];
extern char ttytype[];
extern int tgetflag();
extern int tgetnum();
extern char *tgetstr();
/* externs from libc */
extern void exit();
extern void qsort();
extern char *getenv();
extern int getopt();
extern int optind;
extern char *optarg;
/* data structures for this program */
struct boolstruct {
char *infoname; /* the terminfo capability name */
char *capname; /* the termcap capability name */
char *fullname; /* the long C variable name */
char *secondname; /* the use= terminal w/ this value */
char val; /* the value */
char secondval; /* the value in the use= terminal */
char changed; /* a use= terminal changed the value */
char seenagain; /* a use= terminal had this entry */
};
struct numstruct {
char *infoname; /* ditto from above */
char *capname;
char *fullname;
char *secondname;
short val;
short secondval;
char changed;
char seenagain;
};
struct strstruct {
char *infoname; /* ditto from above */
char *capname;
char *fullname;
char *secondname;
char *val;
char *secondval;
char changed;
char seenagain;
};
/* globals for this file */
char *progname; /* argv[0], the name of the program */
static char *used; /* usage statistics */
static int numbools; /* how many booleans there are */
static int numnums; /* how many numbers there are */
static int numstrs; /* how many strings there are */
#define TTYLEN 255
static char *firstterm; /* the name of the first terminal */
static char *savettytype; /* the synonyms of the first terminal */
/* options */
static int verbose = 0; /* debugging printing level */
static int diff = 0; /* produce diff listing, the default */
static int common = 0; /* produce common listing */
static int neither = 0; /* list caps in neither entry */
static int use = 0; /* produce use= comparison listing */
= pr_none;
static void sortnames();
int numcompare(const void *, const void *);
int boolcompare(const void *, const void *);
int strcompare(const void *, const void *);
static void check_nth_terminal(char *, int);
void
{
exit(-1);
}
/*
Allocate and initialize the global data structures and variables.
*/
void
{
register int i, nullseen;
/* find out how many names we are dealing with */
;
;
;
if (verbose) {
numbools);
numnums);
numstrs);
}
/* Allocate storage for the names and their values */
sizeof (struct boolstruct));
sizeof (struct numstruct));
sizeof (struct strstruct));
/* Allocate array to keep track of which names have been used. */
if (use)
sizeof (char));
badmalloc();
/* Fill in the names and initialize the structures. */
for (i = 0; i < numbools; i++) {
/* This is necessary until fnames.c is */
/* incorporated into standard curses. */
} else
}
nullseen = 0;
for (i = 0; i < numnums; i++) {
} else
}
nullseen = 0;
for (i = 0; i < numstrs; i++) {
} else
}
}
/*
Routines to be passed to qsort(3) for comparison of the structures.
*/
int
boolcompare(const void *x, const void *y)
{
struct boolstruct *a;
struct boolstruct *b;
a = (struct boolstruct *)x;
b = (struct boolstruct *)y;
switch ((int) sortorder) {
case (int) by_terminfo:
case (int) by_cap:
case (int) by_longnames:
default:
return (0);
}
}
int
numcompare(const void *x, const void *y)
{
struct numstruct *a;
struct numstruct *b;
a = (struct numstruct *)x;
b = (struct numstruct *)y;
switch ((int) sortorder) {
case (int) by_terminfo:
case (int) by_cap:
case (int) by_longnames:
default:
return (0);
}
}
int
strcompare(const void *x, const void *y)
{
struct strstruct *a;
struct strstruct *b;
a = (struct strstruct *)x;
b = (struct strstruct *)y;
switch ((int) sortorder) {
case (int) by_terminfo:
case (int) by_cap:
case (int) by_longnames:
default:
return (0);
}
}
/*
Sort the entries by their terminfo name.
*/
static void
{
if (sortorder != by_database) {
sizeof (struct boolstruct), boolcompare);
sizeof (struct numstruct), numcompare);
sizeof (struct strstruct), strcompare);
}
return;
}
/*
Print out a string, or "NULL" if it's not defined.
*/
void
{
else
}
/*
Output the 'ko' termcap string. This is a list of all of the input
keys that input the same thing as the corresponding output strings.
*/
int kncounter;
char kobuffer[512];
char
{
return (koptr);
return (koptr);
*koptr++ = ',';
kncounter++;
}
return (koptr);
}
void
{
char *koptr;
kncounter = 0;
/* get rid of comma */
*(--koptr) = '\0';
}
void
pr_kn()
{
if (kncounter > 0)
}
void
pr_ko()
{
if (kncounter > 0)
}
void
pr_bcaps()
{
char *retptr;
char padbuffer[512];
if (verbose)
if (verbose)
if (verbose)
if (verbose)
if (scroll_forward == NULL)
/* Ignore "xr": Return acts like ce \r \n (Delta Data) */
}
void
pr_ncaps()
{
char padbuffer[512];
int padding;
if (verbose)
/* Duplicate sg for ug: Number of blank chars left by us or ue */
if (magic_cookie_glitch > -1)
if (verbose)
/* Number of millisec of bs delay needed */
if (padding > 0)
if (verbose)
/* Number of millisec of cr delay needed */
if (padding > 0)
if (verbose)
/* Number of millisec of ff delay needed */
if (padding > 0)
if (verbose)
/* Number of millisec of nl delay needed */
if (padding > 0)
if (verbose)
/* Number of millisec of tab delay needed */
if (padding > 0)
/* Handle "kn": Number of "other" keys */
setupknko();
pr_kn();
}
void
pr_scaps()
{
char *retptr;
char padbuffer[512];
/* Backspace if not "^H" */
if (verbose)
/* Newline character (default "\n") */
if (verbose)
/* Handle "ko" here: Termcap entries for other non-function keys */
pr_ko();
/* Ignore "ma": Arrow key map, used by vi version 2 only */
}
/*
Set up the first terminal and save the values from it.
*/
void
initfirstterm(char *term)
{
register int i;
if (verbose)
term);
/* Save the name for later use. */
if (use) {
register unsigned int length;
if (savettytype == NULL) {
"of space\n", progname);
TTYLEN-1);
}
} else
}
pr_bheading();
}
/* Save the values for the first terminal. */
for (i = 0; i < numbools; i++) {
if (verbose)
}
pr_bcaps();
pr_bfooting();
pr_nheading();
}
for (i = 0; i < numnums; i++) {
if (verbose)
}
pr_ncaps();
pr_nfooting();
pr_sheading();
}
for (i = 0; i < numstrs; i++) {
if (verbose) {
}
}
pr_scaps();
pr_sfooting();
}
/*
Set up the n'th terminal.
*/
static void
check_nth_terminal(char *nterm, int n)
{
register char boolval;
register short numval;
register char *strval;
register int i;
if (use)
if (verbose)
nterm);
pr_bheading();
}
(void) printf("comparing %s (TERMINFO=%s) to %s "
"(TERMINFO=%s).\n",
else if (Aflag)
(void) printf("comparing %s (TERMINFO=%s) to %s.\n",
else if (Bflag)
(void) printf("comparing %s to %s (TERMINFO=%s).\n",
else
(void) printf("comparing %s to %s.\n",
(void) printf(" comparing booleans.\n");
}
/* save away the values for the nth terminal */
for (i = 0; i < numbools; i++) {
if (use) {
/*
** We do not have to worry about this impossible case
** since booleans can have only two values: true and
** false.
** if (boolval && (boolval != ibool[i].secondval))
** {
** (void) fprintf(trace, "use= order dependency"
** "found:\n");
** (void) fprintf(trace, " %s: %s has %d, %s has"
** " %d.\n",
** ibool[i].capname, ibool[i].secondname,
** ibool[i].secondval, nterm, boolval);
** }
*/
} else {
else
}
}
}
if (boolval) {
if (verbose)
}
pr_bcaps();
pr_bfooting();
pr_nheading();
}
(void) printf(" comparing numbers.\n");
for (i = 0; i < numnums; i++) {
if (use) {
if ((numval > -1) &&
"%s: use = order dependency "
"found:\n", progname);
"has %d, %s has %d.\n",
}
} else {
if (numval > -1) {
if ((numval > -1) &&
else
}
}
}
if (numval > -1) {
numval);
(void) printf("\t%s: %d:%d.\n",
if (verbose)
"changed = %d, seen = %d.\n",
}
pr_ncaps();
pr_nfooting();
pr_sheading();
}
(void) printf(" comparing strings.\n");
for (i = 0; i < numstrs; i++) {
if (use) {
"use= order dependency"
" found:\n");
" %s: %s has '",
"', %s has '", nterm);
}
} else {
else
}
}
}
(void) printf("'.\n");
}
(void) printf("','");
(void) printf("'.\n");
}
if (verbose) {
}
}
pr_scaps();
pr_sfooting();
return;
}
/*
A capability gets an at-sign if it no longer exists, but
one of the relative entries contains a value for it.
It gets printed if the original value is not seen in ANY
of the relative entries, or if the FIRST relative entry that has
the capability gives a DIFFERENT value for the capability.
*/
void
{
register int i;
/* turn off printing of termcap and long names */
/* print out the entry name */
pr_heading((char *)0, savettytype);
pr_bheading();
/* Print out all bools that are different. */
for (i = 0; i < numbools; i++)
(char *)0, -1);
pr_bfooting();
pr_nheading();
/* Print out all nums that are different. */
for (i = 0; i < numnums; i++)
pr_nfooting();
pr_sheading();
/* Print out all strs that are different. */
for (i = 0; i < numstrs; i++)
(char *)0);
pr_sfooting();
/* Finish it up. */
for (i = firstoptind; i < argc; i++)
if (used[i - firstoptind])
else
"%s: 'use=%s' did not add anything to the "
}
void
local_setenv(char *termNinfo)
{
extern char **environ;
static char *newenviron[2] = { 0, 0 };
register int termlen;
if (verbose)
}
badmalloc();
newenviron[0] = terminfo;
} else
newenviron[0] = (char *) 0;
}
int
{
int i, c, firstoptind;
char *tempargv[2];
/* parse options */
switch (c) {
case 'v': verbose++;
break;
break;
break;
case 'd': diff++;
break;
case 'c': common++;
break;
case 'n': neither++;
break;
case 'u': use++;
break;
break;
break;
break;
break;
break;
case 'r': pr_caprestrict(0);
break;
case 's':
else
goto usage;
break;
case 'V':
exit(0);
case '?':
"usage: %s [-ducn] [-ILC] [-1Vv] "
"[-s d|i|l|c] [-A directory] "
"[-B directory] term-names ...\n",
progname);
"differences (the default for >1 "
"term-name)\n");
"relative description\n");
"entries\n");
"in neither\n");
"entries (the default for 1 term-name)\n");
"entries\n");
"variable names\n");
"output\n");
"version\n");
"debugging output\n");
"order\n");
"for first term-name\n");
"for other term-names\n");
exit(-1);
}
optind = 0;
/* Default to $TERM for -n, -I, -C and -L options. */
/* This is done by faking argv[][], argc and optind. */
if (argc == 0)
else
argc = 2;
optind = 0;
argc = 1;
optind = 0;
}
/* Check for enough names. */
"%s: must have at least two terminal names for a "
"comparison to be done.\n", progname);
goto usage;
}
/* Set the default of diff -d or print -I */
if (argc == 0) {
argc = 1;
optind = 0;
}
} else
diff++;
}
/* Set the default sorting order. */
switch ((int) printing) {
case (int) pr_cap:
case (int) pr_longnames:
sortorder = by_longnames; break;
case (int) pr_terminfo:
case (int) pr_none:
sortorder = by_terminfo; break;
}
sortnames();
if (use)
return (0);
}