4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
22 /* Copyright (c) 1988 AT&T */
23 /* All Rights Reserved */
27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.13 */
35 infocmp - compare terminfo descriptions, or dump a terminfo
39 Tony Hansen, February 23, 1984.
48 /* externs from libcurses */
49 extern char *boolnames
[];
50 extern char *boolcodes
[];
51 extern char *boolfnames
[];
52 extern char *numnames
[];
53 extern char *numcodes
[];
54 extern char *numfnames
[];
55 extern char *strnames
[];
56 extern char *strcodes
[];
57 extern char *strfnames
[];
58 extern char ttytype
[];
59 extern int tgetflag();
61 extern char *tgetstr();
63 /* externs from libc */
66 extern char *getenv();
70 extern char *strncpy(), *strcpy();
71 extern int strcmp(), strlen();
73 /* data structures for this program */
76 char *infoname
; /* the terminfo capability name */
77 char *capname
; /* the termcap capability name */
78 char *fullname
; /* the long C variable name */
79 char *secondname
; /* the use= terminal w/ this value */
80 char val
; /* the value */
81 char secondval
; /* the value in the use= terminal */
82 char changed
; /* a use= terminal changed the value */
83 char seenagain
; /* a use= terminal had this entry */
87 char *infoname
; /* ditto from above */
98 char *infoname
; /* ditto from above */
108 /* globals for this file */
109 char *progname
; /* argv[0], the name of the program */
110 static struct boolstruct
*ibool
; /* array of char information */
111 static struct numstruct
*num
; /* array of number information */
112 static struct strstruct
*str
; /* array of string information */
113 static char *used
; /* usage statistics */
114 static int numbools
; /* how many booleans there are */
115 static int numnums
; /* how many numbers there are */
116 static int numstrs
; /* how many strings there are */
118 static char *firstterm
; /* the name of the first terminal */
119 static char *savettytype
; /* the synonyms of the first terminal */
120 static char _savettytype
[TTYLEN
+1]; /* the place to save those names */
121 static int devnull
; /* open("/dev/null") for setupterm */
122 #define trace stderr /* send trace messages to stderr */
125 static int verbose
= 0; /* debugging printing level */
126 static int diff
= 0; /* produce diff listing, the default */
127 static int common
= 0; /* produce common listing */
128 static int neither
= 0; /* list caps in neither entry */
129 static int use
= 0; /* produce use= comparison listing */
130 static enum printtypes printing
/* doing any of above printing at all */
132 enum { none
, by_database
, by_terminfo
, by_longnames
, by_cap
}
133 sortorder
= none
; /* sort the fields for printing */
134 static char *term1info
, *term2info
; /* $TERMINFO settings */
135 static int Aflag
= 0, Bflag
= 0; /* $TERMINFO was set with -A/-B */
137 #define EQUAL(s1, s2) (((s1 == NULL) && (s2 == NULL)) || \
138 ((s1 != NULL) && (s2 != NULL) && \
139 (strcmp(s1, s2) == 0)))
141 static void sortnames();
142 int numcompare(const void *, const void *);
143 int boolcompare(const void *, const void *);
144 int strcompare(const void *, const void *);
145 static void check_nth_terminal(char *, int);
150 (void) fprintf(stderr
, "%s: malloc is out of space!\n", progname
);
155 Allocate and initialize the global data structures and variables.
158 allocvariables(int argc
, int firstoptind
)
160 register int i
, nullseen
;
162 /* find out how many names we are dealing with */
163 for (numbools
= 0; boolnames
[numbools
]; numbools
++)
165 for (numnums
= 0; numnames
[numnums
]; numnums
++)
167 for (numstrs
= 0; strnames
[numstrs
]; numstrs
++)
171 (void) fprintf(trace
, "There are %d boolean capabilities.\n",
173 (void) fprintf(trace
, "There are %d numeric capabilities.\n",
175 (void) fprintf(trace
, "There are %d string capabilities.\n",
179 /* Allocate storage for the names and their values */
180 ibool
= (struct boolstruct
*) malloc((unsigned) numbools
*
181 sizeof (struct boolstruct
));
182 num
= (struct numstruct
*) malloc((unsigned) numnums
*
183 sizeof (struct numstruct
));
184 str
= (struct strstruct
*) malloc((unsigned) numstrs
*
185 sizeof (struct strstruct
));
187 /* Allocate array to keep track of which names have been used. */
189 used
= (char *) malloc((unsigned) (argc
- firstoptind
) *
192 if ((ibool
== NULL
) || (num
== NULL
) || (str
== NULL
) ||
193 (use
&& (used
== NULL
)))
196 /* Fill in the names and initialize the structures. */
198 for (i
= 0; i
< numbools
; i
++) {
199 ibool
[i
].infoname
= boolnames
[i
];
200 ibool
[i
].capname
= boolcodes
[i
];
201 /* This is necessary until fnames.c is */
202 /* incorporated into standard curses. */
203 if (nullseen
|| (boolfnames
[i
] == NULL
)) {
204 ibool
[i
].fullname
= "unknown_boolean";
207 ibool
[i
].fullname
= boolfnames
[i
];
208 ibool
[i
].changed
= FALSE
;
209 ibool
[i
].seenagain
= FALSE
;
212 for (i
= 0; i
< numnums
; i
++) {
213 num
[i
].infoname
= numnames
[i
];
214 num
[i
].capname
= numcodes
[i
];
215 if (nullseen
|| (numfnames
[i
] == NULL
)) {
216 ibool
[i
].fullname
= "unknown_number";
219 num
[i
].fullname
= numfnames
[i
];
220 num
[i
].changed
= FALSE
;
221 num
[i
].seenagain
= FALSE
;
224 for (i
= 0; i
< numstrs
; i
++) {
225 str
[i
].infoname
= strnames
[i
];
226 str
[i
].capname
= strcodes
[i
];
227 if (nullseen
|| (strfnames
[i
] == NULL
)) {
228 str
[i
].fullname
= "unknown_string";
231 str
[i
].fullname
= strfnames
[i
];
232 str
[i
].changed
= FALSE
;
233 str
[i
].seenagain
= FALSE
;
238 Routines to be passed to qsort(3) for comparison of the structures.
241 boolcompare(const void *x
, const void *y
)
243 struct boolstruct
*a
;
244 struct boolstruct
*b
;
246 a
= (struct boolstruct
*)x
;
247 b
= (struct boolstruct
*)y
;
249 switch ((int) sortorder
) {
250 case (int) by_terminfo
:
251 return (strcmp(a
->infoname
, b
->infoname
));
253 return (strcmp(a
->capname
, b
->capname
));
254 case (int) by_longnames
:
255 return (strcmp(a
->fullname
, b
->fullname
));
262 numcompare(const void *x
, const void *y
)
267 a
= (struct numstruct
*)x
;
268 b
= (struct numstruct
*)y
;
269 switch ((int) sortorder
) {
270 case (int) by_terminfo
:
271 return (strcmp(a
->infoname
, b
->infoname
));
273 return (strcmp(a
->capname
, b
->capname
));
274 case (int) by_longnames
:
275 return (strcmp(a
->fullname
, b
->fullname
));
282 strcompare(const void *x
, const void *y
)
287 a
= (struct strstruct
*)x
;
288 b
= (struct strstruct
*)y
;
290 switch ((int) sortorder
) {
291 case (int) by_terminfo
:
292 return (strcmp(a
->infoname
, b
->infoname
));
294 return (strcmp(a
->capname
, b
->capname
));
295 case (int) by_longnames
:
296 return (strcmp(a
->fullname
, b
->fullname
));
303 Sort the entries by their terminfo name.
308 if (sortorder
!= by_database
) {
309 qsort((char *) ibool
, (unsigned) numbools
,
310 sizeof (struct boolstruct
), boolcompare
);
311 qsort((char *) num
, (unsigned) numnums
,
312 sizeof (struct numstruct
), numcompare
);
313 qsort((char *) str
, (unsigned) numstrs
,
314 sizeof (struct strstruct
), strcompare
);
320 Print out a string, or "NULL" if it's not defined.
323 PR(FILE *stream
, char *string
)
326 (void) fprintf(stream
, "NULL");
332 Output the 'ko' termcap string. This is a list of all of the input
333 keys that input the same thing as the corresponding output strings.
339 *addko(char *output
, char *input
, char *koptr
)
341 char *inptr
, *outptr
, padbuffer
[512];
342 inptr
= tgetstr(input
, (char **)0);
345 outptr
= tgetstr(output
, (char **)0);
348 outptr
= rmpadding(outptr
, padbuffer
, (int *) 0);
349 if (strcmp(inptr
, outptr
) == 0) {
350 *koptr
++ = *output
++;
351 *koptr
++ = *output
++;
366 koptr
= addko("bs", "kb", koptr
); /* key_backspace */
367 koptr
= addko("bt", "kB", koptr
); /* key_btab */
368 koptr
= addko("cl", "kC", koptr
); /* key_clear */
369 koptr
= addko("le", "kl", koptr
); /* key_left */
370 koptr
= addko("do", "kd", koptr
); /* key_down */
371 koptr
= addko("nd", "kr", koptr
); /* key_right */
372 koptr
= addko("up", "ku", koptr
); /* key_up */
373 koptr
= addko("dc", "kD", koptr
); /* key_dc */
374 koptr
= addko("dl", "kL", koptr
); /* key_dl */
375 koptr
= addko("cd", "kS", koptr
); /* key_eos */
376 koptr
= addko("ce", "kE", koptr
); /* key_eol */
377 koptr
= addko("ho", "kh", koptr
); /* key_home */
378 koptr
= addko("st", "kT", koptr
); /* key_stab */
379 koptr
= addko("ic", "kI", koptr
); /* key_ic */
380 koptr
= addko("im", "kI", koptr
); /* key_ic */
381 koptr
= addko("al", "kA", koptr
); /* key_il */
382 koptr
= addko("sf", "kF", koptr
); /* key_sf */
383 koptr
= addko("ll", "kH", koptr
); /* key_ll */
384 koptr
= addko("sr", "kR", koptr
); /* key_sr */
385 koptr
= addko("ei", "kM", koptr
); /* key_eic */
386 koptr
= addko("ct", "ka", koptr
); /* key_catab */
388 /* get rid of comma */
389 if (koptr
!= kobuffer
)
397 pr_number((char *)0, "kn", (char *)0, kncounter
);
404 pr_string((char *)0, "ko", (char *)0, kobuffer
);
414 (void) fprintf(trace
, "looking at 'bs'\n");
415 retptr
= cconvert(rmpadding(cursor_left
, padbuffer
, (int *) 0));
416 if (strcmp("\\b", retptr
) == 0)
417 pr_boolean((char *)0, "bs", (char *)0, 1);
420 (void) fprintf(trace
, "looking at 'pt'\n");
421 retptr
= cconvert(rmpadding(tab
, padbuffer
, (int *) 0));
422 if (strcmp("\\t", retptr
) == 0)
423 pr_boolean((char *)0, "pt", (char *)0, 1);
426 (void) fprintf(trace
, "looking at 'nc'\n");
427 retptr
= cconvert(rmpadding(carriage_return
, padbuffer
, (int *) 0));
428 if (strcmp("\\r", retptr
) != 0)
429 pr_boolean((char *)0, "nc", (char *)0, 1);
432 (void) fprintf(trace
, "looking at 'ns'\n");
433 if (scroll_forward
== NULL
)
434 pr_boolean((char *)0, "ns", (char *)0, 1);
436 /* Ignore "xr": Return acts like ce \r \n (Delta Data) */
446 (void) fprintf(trace
, "looking at 'ug'\n");
447 /* Duplicate sg for ug: Number of blank chars left by us or ue */
448 if (magic_cookie_glitch
> -1)
449 pr_number((char *)0, "ug", (char *)0, magic_cookie_glitch
);
452 (void) fprintf(trace
, "looking at 'dB'\n");
453 /* Number of millisec of bs delay needed */
454 (void) rmpadding(cursor_left
, padbuffer
, &padding
);
456 pr_number((char *)0, "dB", (char *)0, padding
);
459 (void) fprintf(trace
, "looking at 'dC'\n");
460 /* Number of millisec of cr delay needed */
461 (void) rmpadding(carriage_return
, padbuffer
, &padding
);
463 pr_number((char *)0, "dC", (char *)0, padding
);
466 (void) fprintf(trace
, "looking at 'dF'\n");
467 /* Number of millisec of ff delay needed */
468 (void) rmpadding(form_feed
, padbuffer
, &padding
);
470 pr_number((char *)0, "dF", (char *)0, padding
);
473 (void) fprintf(trace
, "looking at 'dN'\n");
474 /* Number of millisec of nl delay needed */
475 (void) rmpadding(cursor_down
, padbuffer
, &padding
);
477 pr_number((char *)0, "dN", (char *)0, padding
);
480 (void) fprintf(trace
, "looking at 'dT'\n");
481 /* Number of millisec of tab delay needed */
482 (void) rmpadding(tab
, padbuffer
, &padding
);
484 pr_number((char *)0, "dT", (char *)0, padding
);
486 /* Handle "kn": Number of "other" keys */
497 /* Backspace if not "^H" */
499 (void) fprintf(trace
, "looking at 'bc'\n");
500 retptr
= cconvert(rmpadding(cursor_left
, padbuffer
, (int *) 0));
501 if (strcmp("\\b", retptr
) != 0)
502 pr_string((char *)0, "bc", (char *)0, cursor_left
);
504 /* Newline character (default "\n") */
506 (void) fprintf(trace
, "looking at 'nl'\n");
507 retptr
= cconvert(rmpadding(cursor_down
, padbuffer
, (int *) 0));
508 if (strcmp("\\n", retptr
) != 0)
509 pr_string((char *)0, "nl", (char *)0, cursor_down
);
511 /* Handle "ko" here: Termcap entries for other non-function keys */
514 /* Ignore "ma": Arrow key map, used by vi version 2 only */
518 Set up the first terminal and save the values from it.
521 initfirstterm(char *term
)
526 (void) fprintf(trace
, "setting up terminal type '%s'.\n",
529 (void) setupterm(term
, devnull
, (int *) 0);
531 /* Save the name for later use. */
533 register unsigned int length
;
534 savettytype
= _savettytype
;
535 if ((length
= strlen(ttytype
)) >= TTYLEN
) {
536 savettytype
= malloc(length
);
537 if (savettytype
== NULL
) {
538 (void) fprintf(stderr
, "%s: malloc is out "
539 "of space\n", progname
);
540 (void) strncpy(_savettytype
, ttytype
,
542 _savettytype
[TTYLEN
] = '\0';
543 savettytype
= _savettytype
;
546 (void) strcpy(_savettytype
, ttytype
);
549 if (printing
!= pr_none
) {
550 pr_heading(term
, ttytype
);
554 /* Save the values for the first terminal. */
555 for (i
= 0; i
< numbools
; i
++) {
556 if ((ibool
[i
].val
= tgetflag(ibool
[i
].capname
)) &&
558 pr_boolean(ibool
[i
].infoname
, ibool
[i
].capname
,
559 ibool
[i
].fullname
, 1);
561 (void) fprintf(trace
, "%s=%d.\n", ibool
[i
].infoname
,
565 if (printing
!= pr_none
) {
566 if (printing
== pr_cap
)
572 for (i
= 0; i
< numnums
; i
++) {
573 if (((num
[i
].val
= tgetnum(num
[i
].capname
)) > -1) &&
575 pr_number(num
[i
].infoname
, num
[i
].capname
,
576 num
[i
].fullname
, num
[i
].val
);
578 (void) fprintf(trace
, "%s=%d.\n", num
[i
].infoname
,
582 if (printing
!= pr_none
) {
583 if (printing
== pr_cap
)
589 for (i
= 0; i
< numstrs
; i
++) {
590 str
[i
].val
= tgetstr(str
[i
].capname
, (char **)0);
591 if ((str
[i
].val
!= NULL
) && printing
!= pr_none
)
592 pr_string(str
[i
].infoname
, str
[i
].capname
,
593 str
[i
].fullname
, str
[i
].val
);
595 (void) fprintf(trace
, "%s='", str
[i
].infoname
);
596 PR(trace
, str
[i
].val
);
597 (void) fprintf(trace
, "'.\n");
601 if (printing
== pr_cap
)
604 if (printing
!= pr_none
)
609 Set up the n'th terminal.
612 check_nth_terminal(char *nterm
, int n
)
614 register char boolval
;
615 register short numval
;
616 register char *strval
;
623 (void) fprintf(trace
, "adding in terminal type '%s'.\n",
626 (void) setupterm(nterm
, devnull
, (int *) 0);
628 if (printing
!= pr_none
) {
629 pr_heading(nterm
, ttytype
);
633 if (diff
|| common
|| neither
) {
635 (void) printf("comparing %s (TERMINFO=%s) to %s "
637 firstterm
, term1info
, nterm
, term2info
);
639 (void) printf("comparing %s (TERMINFO=%s) to %s.\n",
640 firstterm
, term1info
, nterm
);
642 (void) printf("comparing %s to %s (TERMINFO=%s).\n",
643 firstterm
, nterm
, term2info
);
645 (void) printf("comparing %s to %s.\n",
647 (void) printf(" comparing booleans.\n");
650 /* save away the values for the nth terminal */
651 for (i
= 0; i
< numbools
; i
++) {
652 boolval
= tgetflag(ibool
[i
].capname
);
654 if (ibool
[i
].seenagain
) {
656 ** We do not have to worry about this impossible case
657 ** since booleans can have only two values: true and
659 ** if (boolval && (boolval != ibool[i].secondval))
661 ** (void) fprintf(trace, "use= order dependency"
663 ** (void) fprintf(trace, " %s: %s has %d, %s has"
665 ** ibool[i].capname, ibool[i].secondname,
666 ** ibool[i].secondval, nterm, boolval);
670 if (boolval
== TRUE
) {
671 ibool
[i
].seenagain
= TRUE
;
672 ibool
[i
].secondval
= boolval
;
673 ibool
[i
].secondname
= nterm
;
674 if (ibool
[i
].val
!= boolval
)
675 ibool
[i
].changed
= TRUE
;
682 if (printing
!= pr_none
)
683 pr_boolean(ibool
[i
].infoname
, ibool
[i
].capname
,
684 ibool
[i
].fullname
, 1);
685 if (common
&& (ibool
[i
].val
== boolval
))
686 (void) printf("\t%s= T.\n", ibool
[i
].infoname
);
687 } else if (neither
&& !ibool
[i
].val
)
688 (void) printf("\t!%s.\n", ibool
[i
].infoname
);
689 if (diff
&& (ibool
[i
].val
!= boolval
))
690 (void) printf("\t%s: %c:%c.\n", ibool
[i
].infoname
,
691 ibool
[i
].val
?'T':'F', boolval
?'T':'F');
693 (void) fprintf(trace
, "%s: %d:%d, changed=%d, "
694 "seen=%d.\n", ibool
[i
].infoname
, ibool
[i
].val
,
695 boolval
, ibool
[i
].changed
, ibool
[i
].seenagain
);
698 if (printing
!= pr_none
) {
699 if (printing
== pr_cap
)
705 if (diff
|| common
|| neither
)
706 (void) printf(" comparing numbers.\n");
708 for (i
= 0; i
< numnums
; i
++) {
709 numval
= tgetnum(num
[i
].capname
);
711 if (num
[i
].seenagain
) {
713 (numval
!= num
[i
].secondval
)) {
714 (void) fprintf(stderr
,
715 "%s: use = order dependency "
716 "found:\n", progname
);
717 (void) fprintf(stderr
, " %s: %s "
718 "has %d, %s has %d.\n",
719 num
[i
].capname
, num
[i
].secondname
,
720 num
[i
].secondval
, nterm
, numval
);
724 num
[i
].seenagain
= TRUE
;
725 num
[i
].secondval
= numval
;
726 num
[i
].secondname
= nterm
;
728 (num
[i
].val
!= numval
))
729 num
[i
].changed
= TRUE
;
736 if (printing
!= pr_none
)
737 pr_number(num
[i
].infoname
, num
[i
].capname
,
738 num
[i
].fullname
, numval
);
739 if (common
&& (num
[i
].val
== numval
))
740 (void) printf("\t%s= %d.\n", num
[i
].infoname
,
742 } else if (neither
&& (num
[i
].val
== -1))
743 (void) printf("\t!%s.\n", num
[i
].infoname
);
744 if (diff
&& (num
[i
].val
!= numval
))
745 (void) printf("\t%s: %d:%d.\n",
746 num
[i
].infoname
, num
[i
].val
, numval
);
748 (void) fprintf(trace
, "%s: %d:%d, "
749 "changed = %d, seen = %d.\n",
750 num
[i
].infoname
, num
[i
].val
, numval
,
751 num
[i
].changed
, num
[i
].seenagain
);
754 if (printing
!= pr_none
) {
755 if (printing
== pr_cap
)
761 if (diff
|| common
|| neither
)
762 (void) printf(" comparing strings.\n");
764 for (i
= 0; i
< numstrs
; i
++) {
765 strval
= tgetstr(str
[i
].capname
, (char **)0);
767 if (str
[i
].seenagain
&& (strval
!= NULL
)) {
768 if (!EQUAL(strval
, str
[i
].secondval
)) {
769 (void) fprintf(stderr
,
770 "use= order dependency"
772 (void) fprintf(stderr
,
774 str
[i
].capname
, str
[i
].secondname
);
775 PR(stderr
, str
[i
].secondval
);
776 (void) fprintf(stderr
,
777 "', %s has '", nterm
);
779 (void) fprintf(stderr
, "'.\n");
782 if (strval
!= NULL
) {
783 str
[i
].seenagain
= TRUE
;
784 str
[i
].secondval
= strval
;
785 str
[i
].secondname
= nterm
;
786 if (!EQUAL(str
[i
].val
, strval
))
787 str
[i
].changed
= TRUE
;
793 if (strval
!= NULL
) {
794 if (printing
!= pr_none
)
795 pr_string(str
[i
].infoname
, str
[i
].capname
,
796 str
[i
].fullname
, strval
);
797 if (common
&& EQUAL(str
[i
].val
, strval
)) {
798 (void) printf("\t%s= '", str
[i
].infoname
);
800 (void) printf("'.\n");
802 } else if (neither
&& (str
[i
].val
== NULL
))
803 (void) printf("\t!%s.\n", str
[i
].infoname
);
804 if (diff
&& !EQUAL(str
[i
].val
, strval
)) {
805 (void) printf("\t%s: '", str
[i
].infoname
);
806 PR(stdout
, str
[i
].val
);
807 (void) printf("','");
809 (void) printf("'.\n");
812 (void) fprintf(trace
, "%s: '", str
[i
].infoname
);
813 PR(trace
, str
[i
].val
);
814 (void) fprintf(trace
, "':'");
816 (void) fprintf(trace
, "',changed=%d,seen=%d.\n",
817 str
[i
].changed
, str
[i
].seenagain
);
821 if (printing
== pr_cap
)
824 if (printing
!= pr_none
)
831 A capability gets an at-sign if it no longer exists, but
832 one of the relative entries contains a value for it.
833 It gets printed if the original value is not seen in ANY
834 of the relative entries, or if the FIRST relative entry that has
835 the capability gives a DIFFERENT value for the capability.
838 dorelative(int firstoptind
, int argc
, char **argv
)
842 /* turn off printing of termcap and long names */
843 pr_init(pr_terminfo
);
845 /* print out the entry name */
846 pr_heading((char *)0, savettytype
);
850 /* Print out all bools that are different. */
851 for (i
= 0; i
< numbools
; i
++)
852 if (!ibool
[i
].val
&& ibool
[i
].changed
)
853 pr_boolean(ibool
[i
].infoname
, (char *)0,
855 else if (ibool
[i
].val
&& (ibool
[i
].changed
||
856 !ibool
[i
].seenagain
))
857 pr_boolean(ibool
[i
].infoname
, (char *)0, (char *)0, 1);
862 /* Print out all nums that are different. */
863 for (i
= 0; i
< numnums
; i
++)
864 if (num
[i
].val
< 0 && num
[i
].changed
)
865 pr_number(num
[i
].infoname
, (char *)0, (char *)0, -1);
866 else if (num
[i
].val
>= 0 && (num
[i
].changed
||
868 pr_number(num
[i
].infoname
, (char *)0,
869 (char *)0, num
[i
].val
);
874 /* Print out all strs that are different. */
875 for (i
= 0; i
< numstrs
; i
++)
876 if (str
[i
].val
== NULL
&& str
[i
].changed
)
877 pr_string(str
[i
].infoname
, (char *)0, (char *)0,
879 else if ((str
[i
].val
!= NULL
) &&
880 (str
[i
].changed
|| !str
[i
].seenagain
))
881 pr_string(str
[i
].infoname
, (char *)0, (char *)0, str
[i
].val
);
886 for (i
= firstoptind
; i
< argc
; i
++)
887 if (used
[i
- firstoptind
])
888 (void) printf("\tuse=%s,\n", argv
[i
]);
890 (void) fprintf(stderr
,
891 "%s: 'use=%s' did not add anything to the "
892 "description.\n", progname
, argv
[i
]);
896 local_setenv(char *termNinfo
)
898 extern char **environ
;
899 static char *newenviron
[2] = { 0, 0 };
900 static unsigned int termsize
= BUFSIZ
;
901 static char _terminfo
[BUFSIZ
];
902 static char *terminfo
= &_terminfo
[0];
903 register int termlen
;
905 if (termNinfo
&& *termNinfo
) {
907 (void) fprintf(trace
, "setting TERMINFO=%s.\n",
909 termlen
= strlen(termNinfo
);
910 if (termlen
+ 10 > termsize
) {
911 termsize
= termlen
+ 20;
912 terminfo
= (char *) malloc(termsize
* sizeof (char));
914 if (terminfo
== (char *) NULL
)
916 (void) sprintf(terminfo
, "TERMINFO=%s", termNinfo
);
917 newenviron
[0] = terminfo
;
919 newenviron
[0] = (char *) 0;
920 environ
= newenviron
;
924 main(int argc
, char **argv
)
926 int i
, c
, firstoptind
;
928 char *term
= getenv("TERM");
930 term1info
= term2info
= getenv("TERMINFO");
934 while ((c
= getopt(argc
, argv
, "ducnILCvV1rw:s:A:B:")) != EOF
)
938 case '1': pr_onecolumn(1);
940 case 'w': pr_width(atoi(optarg
));
950 case 'L': pr_init(printing
= pr_longnames
);
952 case 'I': pr_init(printing
= pr_terminfo
);
954 case 'C': pr_init(printing
= pr_cap
);
956 case 'A': term1info
= optarg
; Aflag
++;
958 case 'B': term2info
= optarg
; Bflag
++;
960 case 'r': pr_caprestrict(0);
963 if (strcmp(optarg
, "d") == 0)
964 sortorder
= by_database
;
965 else if (strcmp(optarg
, "i") == 0)
966 sortorder
= by_terminfo
;
967 else if (strcmp(optarg
, "l") == 0)
968 sortorder
= by_longnames
;
969 else if (strcmp(optarg
, "c") == 0)
975 (void) printf("%s: version %s\n", progname
,
976 "@(#)curses:screen/infocmp.c 1.13");
980 (void) fprintf(stderr
,
981 "usage: %s [-ducn] [-ILC] [-1Vv] "
982 "[-s d|i|l|c] [-A directory] "
983 "[-B directory] term-names ...\n",
985 (void) fprintf(stderr
, "\t-d\tprint "
986 "differences (the default for >1 "
988 (void) fprintf(stderr
, "\t-u\tproduce "
989 "relative description\n");
990 (void) fprintf(stderr
, "\t-c\tprint common "
992 (void) fprintf(stderr
, "\t-n\tprint entries "
994 (void) fprintf(stderr
, "\t-I\tprint terminfo "
995 "entries (the default for 1 term-name)\n");
996 (void) fprintf(stderr
, "\t-C\tprint termcap "
998 (void) fprintf(stderr
, "\t-L\tprint long C "
1000 (void) fprintf(stderr
, "\t-1\tsingle column "
1002 (void) fprintf(stderr
, "\t-V\tprint program "
1004 (void) fprintf(stderr
, "\t-v\tverbose "
1005 "debugging output\n");
1006 (void) fprintf(stderr
, "\t-s\tchange sort "
1008 (void) fprintf(stderr
, "\t-A\tset $TERMINFO "
1009 "for first term-name\n");
1010 (void) fprintf(stderr
, "\t-B\tset $TERMINFO "
1011 "for other term-names\n");
1019 /* Default to $TERM for -n, -I, -C and -L options. */
1020 /* This is done by faking argv[][], argc and optind. */
1021 if (neither
&& (argc
== 0 || argc
== 1)) {
1025 tempargv
[0] = argv
[optind
];
1030 } else if ((printing
!= pr_none
) && (argc
== 0)) {
1037 /* Check for enough names. */
1038 if ((use
|| diff
|| common
) && (argc
<= 1)) {
1039 (void) fprintf(stderr
,
1040 "%s: must have at least two terminal names for a "
1041 "comparison to be done.\n", progname
);
1045 /* Set the default of diff -d or print -I */
1046 if (!use
&& (printing
== pr_none
) && !common
&& !neither
) {
1047 if (argc
== 0 || argc
== 1) {
1054 pr_init(printing
= pr_terminfo
);
1059 /* Set the default sorting order. */
1060 if (sortorder
== none
)
1061 switch ((int) printing
) {
1063 sortorder
= by_cap
; break;
1064 case (int) pr_longnames
:
1065 sortorder
= by_longnames
; break;
1066 case (int) pr_terminfo
:
1068 sortorder
= by_terminfo
; break;
1071 firstterm
= argv
[optind
++];
1072 firstoptind
= optind
;
1074 allocvariables(argc
, firstoptind
);
1077 devnull
= open("/dev/null", O_RDWR
);
1078 local_setenv(term1info
);
1079 initfirstterm(firstterm
);
1080 local_setenv(term2info
);
1081 for (i
= 0; optind
< argc
; optind
++, i
++)
1082 check_nth_terminal(argv
[optind
], i
);
1085 dorelative(firstoptind
, argc
, argv
);