infocmp.c

Upload User: acmefrp
Upload Date: 2010-03-06
Package Size: 23768k
Code Size: 27k
Category: OS Develop
Development Platform: C/C++
  1. /* Copyright (c) 1984 AT&T */
  2. /*   All Rights Reserved   */
  3. /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
  4. /* The copyright notice above does not evidence any    */
  5. /* actual or intended publication of such source code. */
  6. #ifndef lint
  7. static char sccsid[] = "@(#)infocmp.c 1.1 92/07/30 SMI"; /* from S5R3 1.11.1.1 */
  8. #endif
  9. /*
  10.     NAME
  11. infocmp - compare terminfo descriptions, or dump a terminfo
  12.   description
  13.     AUTHOR
  14. Tony Hansen, February 23, 1984.
  15. */
  16. #include "curses.h"
  17. #include "term.h"
  18. #include "print.h"
  19. #include <fcntl.h>
  20. /* externs from libcurses */
  21. extern char *boolnames[];
  22. extern char *boolcodes[];
  23. extern char *boolfnames[];
  24. extern char *numnames[];
  25. extern char *numcodes[];
  26. extern char *numfnames[];
  27. extern char *strnames[];
  28. extern char *strcodes[];
  29. extern char *strfnames[];
  30. extern char ttytype[];
  31. extern int tgetflag ();
  32. extern int tgetnum ();
  33. extern char *tgetstr ();
  34. /* externs from libc */
  35. extern char *malloc ();
  36. extern void exit ();
  37. extern void qsort ();
  38. extern char *getenv ();
  39. extern int getopt ();
  40. extern int optind;
  41. extern char *optarg;
  42. extern char *strncpy(), *strcpy();
  43. extern int strcmp(), strlen();
  44. /* data structures for this program */
  45. struct boolstruct
  46.     {
  47.     char *infoname; /* the terminfo capability name */
  48.     char *capname; /* the termcap capability name */
  49.     char *fullname; /* the long C variable name */
  50.     char *secondname; /* the use= terminal w/ this value */
  51.     char val; /* the value */
  52.     char secondval; /* the value in the use= terminal */
  53.     char changed; /* a use= terminal changed the value */
  54.     char seenagain; /* a use= terminal had this entry */
  55.     };
  56. struct numstruct
  57.     {
  58.     char *infoname; /* ditto from above */
  59.     char *capname;
  60.     char *fullname;
  61.     char *secondname;
  62.     short val;
  63.     short secondval;
  64.     char changed;
  65.     char seenagain;
  66.     };
  67. struct strstruct
  68.     {
  69.     char *infoname; /* ditto from above */
  70.     char *capname;
  71.     char *fullname;
  72.     char *secondname;
  73.     char *val;
  74.     char *secondval;
  75.     char changed;
  76.     char seenagain;
  77.     };
  78. /* globals for this file */
  79. char *progname; /* argv[0], the name of the program */
  80. static struct boolstruct *ibool;/* array of char information */
  81. static struct numstruct *num; /* array of number information */
  82. static struct strstruct *str; /* array of string information */
  83. static char *used; /* usage statistics */
  84. static int numbools; /* how many booleans there are */
  85. static int numnums; /* how many numbers there are */
  86. static int numstrs; /* how many strings there are */
  87. #define TTYLEN 255
  88. static char *firstterm; /* the name of the first terminal */
  89. static char *savettytype; /* the synonyms of the first terminal */
  90. static char _savettytype[TTYLEN];/* the place to save those names */
  91. static int devnull; /* open("/dev/null") for setupterm */
  92. #define trace stderr /* send trace messages to stderr */
  93. /* options */
  94. static int verbose = 0; /* debugging printing level */
  95. static int diff = 0; /* produce diff listing, the default */
  96. static int common = 0; /* produce common listing */
  97. static int neither = 0; /* list caps in neither entry */
  98. static int use = 0; /* produce use= comparison listing */
  99. static enum printtypes printing /* doing any of above printing at all */
  100. = pr_none;
  101. enum { none, by_database, by_terminfo, by_longnames, by_cap }
  102.     sortorder = none; /* sort the fields for printing */
  103. static char *term1info, *term2info; /* $TERMINFO settings */
  104. static int Aflag = 0, Bflag = 0; /* $TERMINFO was set with -A/-B */
  105. #define EQUAL(s1,s2) ( ((s1 == NULL) && (s2 == NULL)) || 
  106.   ((s1 != NULL) && (s2 != NULL) && 
  107.   (strcmp(s1,s2) == 0) ) )
  108. void badmalloc()
  109. {
  110.     (void) fprintf (stderr, "%s: malloc is out of space!n", progname);
  111.     exit (-1);
  112. }
  113. /*
  114.     Allocate and initialize the global data structures and variables.
  115. */
  116. void allocvariables(argc, firstoptind)
  117. int argc, firstoptind;
  118. {
  119.     register int i, nullseen;
  120.     /* find out how many names we are dealing with */
  121.     for (numbools = 0; boolnames[numbools]; numbools++)
  122. ;
  123.     for (numnums = 0; numnames[numnums]; numnums++)
  124. ;
  125.     for (numstrs = 0; strnames[numstrs]; numstrs++)
  126. ;
  127.     if (verbose)
  128. {
  129. (void) fprintf (trace, "There are %d boolean capabilities.n", numbools);
  130. (void) fprintf (trace, "There are %d numeric capabilities.n", numnums);
  131. (void) fprintf (trace, "There are %d string capabilities.n", numstrs);
  132. }
  133.     /* Allocate storage for the names and their values */
  134.     ibool = (struct boolstruct  *) malloc ((unsigned) numbools * sizeof (struct boolstruct));
  135.     num = (struct numstruct *) malloc ((unsigned) numnums * sizeof (struct numstruct));
  136.     str = (struct strstruct *) malloc ((unsigned) numstrs * sizeof (struct strstruct));
  137.     /* Allocate array to keep track of which names have been used. */
  138.     if (use)
  139. used = (char *) malloc ((unsigned) (argc - firstoptind) * sizeof (char));
  140.     if ((ibool == NULL) || (num == NULL) || (str == NULL) ||
  141.     (use && (used == NULL)))
  142. badmalloc();
  143.     /* Fill in the names and initialize the structures. */
  144.     nullseen = FALSE;
  145.     for (i = 0; i < numbools; i++)
  146. {
  147. ibool[i].infoname = boolnames[i];
  148. ibool[i].capname = boolcodes[i];
  149. /* This is necessary until fnames.c is */
  150. /* incorporated into standard curses. */
  151. if (nullseen || (boolfnames[i] == NULL))
  152.     {
  153.     ibool[i].fullname = "unknown_boolean";
  154.     nullseen = TRUE;
  155.     }
  156. else
  157.     ibool[i].fullname = boolfnames[i];
  158. ibool[i].changed = FALSE;
  159. ibool[i].seenagain = FALSE;
  160. }
  161.     nullseen = 0;
  162.     for (i = 0; i < numnums; i++)
  163. {
  164. num[i].infoname = numnames[i];
  165. num[i].capname = numcodes[i];
  166. if (nullseen || (numfnames[i] == NULL))
  167.     {
  168.     ibool[i].fullname = "unknown_number";
  169.     nullseen = TRUE;
  170.     }
  171. else
  172.     num[i].fullname = numfnames[i];
  173. num[i].changed = FALSE;
  174. num[i].seenagain = FALSE;
  175. }
  176.     nullseen = 0;
  177.     for (i = 0; i < numstrs; i++)
  178. {
  179. str[i].infoname = strnames[i];
  180. str[i].capname = strcodes[i];
  181. if (nullseen || (strfnames[i] == NULL))
  182.     {
  183.     str[i].fullname = "unknown_string";
  184.     nullseen = TRUE;
  185.     }
  186. else
  187.     str[i].fullname = strfnames[i];
  188. str[i].changed = FALSE;
  189. str[i].seenagain = FALSE;
  190. }
  191. }
  192. /*
  193.     Routines to be passed to qsort(3) for comparison of the structures.
  194. */
  195. int boolcompare (a, b)
  196. struct boolstruct *a, *b;
  197. {
  198.     switch ( (int) sortorder)
  199. {
  200. case (int) by_terminfo:  return strcmp (a->infoname, b->infoname);
  201. case (int) by_cap:  return strcmp (a->capname, b->capname);
  202. case (int) by_longnames: return strcmp (a->fullname, b->fullname);
  203. default:  return 0;
  204. }
  205. }
  206. int numcompare (a, b)
  207. struct numstruct *a, *b;
  208. {
  209.     switch ( (int) sortorder)
  210. {
  211. case (int) by_terminfo:  return strcmp (a->infoname, b->infoname);
  212. case (int) by_cap:  return strcmp (a->capname, b->capname);
  213. case (int) by_longnames: return strcmp (a->fullname, b->fullname);
  214. default:  return 0;
  215. }
  216. }
  217. int strcompare (a, b)
  218. struct strstruct *a, *b;
  219. {
  220.     switch ( (int) sortorder)
  221. {
  222. case (int) by_terminfo:  return strcmp (a->infoname, b->infoname);
  223. case (int) by_cap:  return strcmp (a->capname, b->capname);
  224. case (int) by_longnames: return strcmp (a->fullname, b->fullname);
  225. default:  return 0;
  226. }
  227. }
  228. /*
  229.     Sort the entries by their terminfo name.
  230. */
  231. sortnames()
  232. {
  233.     if (sortorder != by_database)
  234. {
  235. qsort ((char *) ibool, (unsigned) numbools, sizeof (struct boolstruct)  , boolcompare);
  236. qsort ((char *) num, (unsigned) numnums, sizeof (struct numstruct) , numcompare);
  237. qsort ((char *) str, (unsigned) numstrs, sizeof (struct strstruct) , strcompare);
  238. }
  239. }
  240. /*
  241.     Print out a string, or "NULL" if it's not defined.
  242. */
  243. void PR (stream, string)
  244. FILE *stream;
  245. register char *string;
  246. {
  247.     if (string == NULL)
  248. (void) fprintf (stream, "NULL");
  249.     else
  250. tpr (stream, string);
  251. }
  252. /*
  253.     Output the 'ko' termcap string. This is a list of all of the input
  254.     keys that input the same thing as the corresponding output strings.    
  255. */
  256. int kncounter;
  257. char kobuffer[512];
  258. char *addko (output, input, koptr)
  259. char *output, *input, *koptr;
  260. {
  261.     char *inptr, *outptr, padbuffer[512];
  262.     inptr = tgetstr (input, (char **)0);
  263.     if (inptr == NULL)
  264.         return koptr;
  265.     outptr = tgetstr (output, (char **)0);
  266.     if (outptr == NULL)
  267.         return koptr;
  268.     outptr = rmpadding (outptr, padbuffer, (int *) 0);
  269.     if (strcmp (inptr, outptr) == 0)
  270.         {
  271.         *koptr++ = *output++;
  272. *koptr++ = *output++;
  273. *koptr++ = ',';
  274. kncounter++;
  275. }
  276.     return koptr;
  277. }
  278. void setupknko()
  279. {
  280.     char *koptr;
  281.     
  282.     kncounter = 0;
  283.     koptr = kobuffer;
  284.     koptr = addko("bs", "kb", koptr); /* key_backspace */
  285.     koptr = addko("bt", "kB", koptr); /* key_btab */
  286.     koptr = addko("cl", "kC", koptr); /* key_clear */
  287.     koptr = addko("le", "kl", koptr); /* key_left */
  288.     koptr = addko("do", "kd", koptr); /* key_down */
  289.     koptr = addko("nd", "kr", koptr); /* key_right */
  290.     koptr = addko("up", "ku", koptr); /* key_up */
  291.     koptr = addko("dc", "kD", koptr); /* key_dc */
  292.     koptr = addko("dl", "kL", koptr); /* key_dl */
  293.     koptr = addko("cd", "kS", koptr); /* key_eos */
  294.     koptr = addko("ce", "kE", koptr); /* key_eol */
  295.     koptr = addko("ho", "kh", koptr); /* key_home */
  296.     koptr = addko("st", "kT", koptr); /* key_stab */
  297.     koptr = addko("ic", "kI", koptr); /* key_ic */
  298.     koptr = addko("im", "kI", koptr); /* key_ic */
  299.     koptr = addko("al", "kA", koptr); /* key_il */
  300.     koptr = addko("sf", "kF", koptr); /* key_sf */
  301.     koptr = addko("ll", "kH", koptr); /* key_ll */
  302.     koptr = addko("sr", "kR", koptr); /* key_sr */
  303.     koptr = addko("ei", "kM", koptr); /* key_eic */
  304.     koptr = addko("ct", "ka", koptr); /* key_catab */
  305.     /* get rid of comma */
  306.     if (koptr != kobuffer)
  307.         *(--koptr) = '';
  308. }
  309. void pr_kn()
  310. {
  311.     if (kncounter > 0)
  312.         pr_number ((char *)0, "kn", (char *)0, kncounter);
  313. }
  314. void pr_ko()
  315. {
  316.     if (kncounter > 0)
  317. pr_string ((char *)0, "ko", (char *)0, kobuffer);
  318. }
  319. void pr_bcaps()
  320. {
  321.     char *retptr;
  322.     char padbuffer[512];
  323.     if (verbose)
  324.         (void) fprintf (trace, "looking at 'bs'n");
  325.     retptr = cconvert (rmpadding (cursor_left, padbuffer, (int *) 0));
  326.     if (strcmp ("\b", retptr) == 0)
  327. pr_boolean ((char *)0, "bs", (char *)0, 1);
  328.     if (verbose)
  329.         (void) fprintf (trace, "looking at 'pt'n");
  330.     retptr = cconvert (rmpadding (tab, padbuffer, (int *) 0));
  331.     if (strcmp ("\t", retptr) == 0)
  332. pr_boolean ((char *)0, "pt", (char *)0, 1);
  333.     if (verbose)
  334.         (void) fprintf (trace, "looking at 'nc'n");
  335.     retptr = cconvert (rmpadding (carriage_return, padbuffer, (int *) 0));
  336.     if (strcmp ("\r", retptr) != 0)
  337. pr_boolean ((char *)0, "nc", (char *)0, 1);
  338.     if (verbose)
  339.         (void) fprintf (trace, "looking at 'ns'n");
  340.     if (scroll_forward == NULL)
  341. pr_boolean ((char *)0, "ns", (char *)0, 1);
  342.     /* Ignore "xr": Return acts like ce r n (Delta Data) */
  343. }
  344. void pr_ncaps()
  345. {
  346.     char padbuffer[512];
  347.     int padding;
  348.     if (verbose)
  349.         (void) fprintf (trace, "looking at 'ug'n");
  350.     /* Duplicate sg for ug: Number of blank chars left by us or ue */
  351.     if (magic_cookie_glitch > -1)
  352. pr_number ((char *)0, "ug", (char *)0, magic_cookie_glitch);
  353.     if (verbose)
  354.         (void) fprintf (trace, "looking at 'dB'n");
  355.     /* Number of millisec of bs delay needed */
  356.     (void) rmpadding (cursor_left, padbuffer, &padding);
  357.     if (padding > 0)
  358. pr_number ((char *)0, "dB", (char *)0, padding);
  359.     if (verbose)
  360.         (void) fprintf (trace, "looking at 'dC'n");
  361.     /* Number of millisec of cr delay needed */
  362.     (void) rmpadding (carriage_return, padbuffer, &padding);
  363.     if (padding > 0)
  364. pr_number ((char *)0, "dC", (char *)0, padding);
  365.     if (verbose)
  366.         (void) fprintf (trace, "looking at 'dF'n");
  367.     /* Number of millisec of ff delay needed */
  368.     (void) rmpadding (form_feed, padbuffer, &padding);
  369.     if (padding > 0)
  370. pr_number ((char *)0, "dF", (char *)0, padding);
  371.     if (verbose)
  372.         (void) fprintf (trace, "looking at 'dN'n");
  373.     /* Number of millisec of nl delay needed */
  374.     (void) rmpadding (cursor_down, padbuffer, &padding);
  375.     if (padding > 0)
  376. pr_number ((char *)0, "dN", (char *)0, padding);
  377.     if (verbose)
  378.         (void) fprintf (trace, "looking at 'dT'n");
  379.     /* Number of millisec of tab delay needed */
  380.     (void) rmpadding (tab, padbuffer, &padding);
  381.     if (padding > 0)
  382. pr_number ((char *)0, "dT", (char *)0, padding);
  383.     /* Handle "kn": Number of "other" keys */
  384.     setupknko();
  385.     pr_kn();
  386. }
  387. void pr_scaps()
  388. {
  389.     char *retptr;
  390.     char padbuffer[512];
  391.     /* Backspace if not "^H" */
  392.     if (verbose)
  393.         (void) fprintf (trace, "looking at 'bc'n");
  394.     retptr = cconvert (rmpadding (cursor_left, padbuffer, (int *) 0));
  395.     if (strcmp ("\b", retptr) != 0)
  396. pr_string ((char *)0, "bc", (char *)0, cursor_left);
  397.     /* Newline character (default "n") */
  398.     if (verbose)
  399.         (void) fprintf (trace, "looking at 'nl'n");
  400.     retptr = cconvert (rmpadding (cursor_down, padbuffer, (int *) 0));
  401.     if (strcmp ("\n", retptr) != 0)
  402. pr_string ((char *)0, "nl", (char *)0, cursor_down);
  403.     /* Handle "ko" here: Termcap entries for other non-function keys */
  404.     pr_ko();
  405.     /* Ignore "ma": Arrow key map, used by vi version 2 only */
  406. }
  407. /*
  408.     Set up the first terminal and save the values from it.
  409. */
  410. void initfirstterm (term)
  411. register char *term;
  412. {
  413.     register int i;
  414.     if (verbose)
  415. (void) fprintf (trace, "setting up terminal type '%s'.n", term);
  416.     (void) setupterm (term, devnull, (int *) 0);
  417.     /* Save the name for later use. */
  418.     if (use)
  419. {
  420. register unsigned int length;
  421. savettytype = _savettytype;
  422. if ((length = strlen(ttytype)) >= TTYLEN)
  423.     {
  424.     savettytype = malloc (length);
  425.     if (savettytype == NULL)
  426. {
  427. (void) fprintf (stderr, "%s: malloc is out of spacen",
  428.     progname);
  429. (void) strncpy (_savettytype, ttytype, TTYLEN-1);
  430. _savettytype[TTYLEN] = '';
  431. savettytype = _savettytype;
  432. }
  433.     }
  434. else
  435.     (void) strcpy (_savettytype, ttytype);
  436. }
  437.     if (printing != pr_none)
  438. {
  439. pr_heading (term, ttytype);
  440. pr_bheading ();
  441. }
  442.     /* Save the values for the first terminal. */
  443.     for (i = 0; i < numbools; i++)
  444. {
  445. if ((ibool[i].val = tgetflag (ibool[i].capname)) &&
  446.     printing != pr_none)
  447.     pr_boolean (ibool[i].infoname, ibool[i].capname, ibool[i].fullname, 1);
  448. if (verbose)
  449.     (void) fprintf (trace, "%s=%d.n", ibool[i].infoname, ibool[i].val);
  450. }
  451.     if (printing != pr_none)
  452. {
  453. if (printing == pr_cap)
  454.     pr_bcaps();
  455. pr_bfooting();
  456. pr_nheading();
  457. }
  458.     for (i = 0; i < numnums; i++)
  459. {
  460. if (((num[i].val = tgetnum (num[i].capname)) > -1) && 
  461.     printing != pr_none)
  462.     pr_number (num[i].infoname, num[i].capname, num[i].fullname, num[i].val);
  463. if (verbose)
  464.     (void) fprintf (trace, "%s=%d.n", num[i].infoname, num[i].val);
  465. }
  466.     if (printing != pr_none)
  467. {
  468. if (printing == pr_cap)
  469.     pr_ncaps();
  470. pr_nfooting();
  471. pr_sheading();
  472. }
  473.     for (i = 0; i < numstrs; i++)
  474. {
  475. str[i].val = tgetstr (str[i].capname, (char **)0);
  476. if ((str[i].val != NULL) && printing != pr_none)
  477.     pr_string (str[i].infoname, str[i].capname, str[i].fullname, str[i].val);
  478. if (verbose)
  479.     {
  480.     (void) fprintf (trace, "%s='", str[i].infoname);
  481.     PR (trace, str[i].val);
  482.     (void) fprintf (trace, "'.n");
  483.     }
  484. }
  485.     if (printing == pr_cap)
  486. pr_scaps();
  487.     if (printing != pr_none)
  488. pr_sfooting();
  489. }
  490. /*
  491.     Set up the n'th terminal.
  492. */
  493. check_nth_terminal (nterm, n)
  494. char *nterm;
  495. int n;
  496. {
  497.     register char boolval;
  498.     register short numval;
  499.     register char *strval;
  500.     register int i;
  501.     if (use)
  502. used[n] = FALSE;
  503.     if (verbose)
  504. (void) fprintf (trace, "adding in terminal type '%s'.n", nterm);
  505.     (void) setupterm (nterm, devnull, (int *) 0);
  506.     if (printing != pr_none)
  507. {
  508. pr_heading (nterm, ttytype);
  509. pr_bheading ();
  510. }
  511.     if (diff || common || neither)
  512. {
  513. if (Aflag && Bflag)
  514.     (void) printf ("comparing %s (TERMINFO=%s) to %s (TERMINFO=%s).n",
  515.         firstterm, term1info, nterm, term2info);
  516. else if (Aflag)
  517.     (void) printf ("comparing %s (TERMINFO=%s) to %s.n",
  518.         firstterm, term1info, nterm);
  519. else if (Bflag)
  520.     (void) printf ("comparing %s to %s (TERMINFO=%s).n",
  521.     firstterm, nterm, term2info);
  522. else
  523.     (void) printf ("comparing %s to %s.n", firstterm, nterm);
  524. (void) printf ("    comparing booleans.n");
  525. }
  526.     /* save away the values for the nth terminal */
  527.     for (i = 0; i < numbools; i++)
  528. {
  529. boolval = tgetflag (ibool[i].capname);
  530. if (use)
  531.     {
  532.     if (ibool[i].seenagain)
  533. {
  534. /* We do not have to worry about this impossible case
  535. ** since booleans can have only two values: true and false.
  536. ** if (boolval && (boolval != ibool[i].secondval))
  537. **  {
  538. **  (void) fprintf (trace, "use= order dependency found:n");
  539. **  (void) fprintf (trace, "    %s: %s has %d, %s has %d.n",
  540. ** ibool[i].capname, ibool[i].secondname,
  541. ** ibool[i].secondval, nterm, boolval);
  542. **  }
  543. */
  544. }
  545.     else
  546. {
  547. if (boolval == TRUE)
  548.     {
  549.     ibool[i].seenagain = TRUE;
  550.     ibool[i].secondval = boolval;
  551.     ibool[i].secondname = nterm;
  552.     if (ibool[i].val != boolval)
  553. ibool[i].changed = TRUE;
  554.     else
  555. used[n] = TRUE;
  556.     }
  557. }
  558.     }
  559. if (boolval)
  560.     {
  561.     if (printing != pr_none)
  562. pr_boolean (ibool[i].infoname, ibool[i].capname, ibool[i].fullname, 1);
  563.     if (common && (ibool[i].val == boolval))
  564. (void) printf ("t%s= T.n", ibool[i].infoname);
  565.     }
  566. else if (neither && !ibool[i].val)
  567.     (void) printf ("t!%s.n", ibool[i].infoname);
  568. if (diff && (ibool[i].val != boolval))
  569.     (void) printf ("t%s: %c:%c.n", ibool[i].infoname,
  570.     ibool[i].val?'T':'F', boolval?'T':'F');
  571. if (verbose)
  572.     (void) fprintf (trace, "%s: %d:%d,changed=%d,seen=%d.n",
  573.     ibool[i].infoname, ibool[i].val, boolval,
  574.     ibool[i].changed, ibool[i].seenagain);
  575. }
  576.     if (printing != pr_none)
  577. {
  578. if (printing == pr_cap)
  579.     pr_bcaps();
  580. pr_bfooting();
  581. pr_nheading();
  582. }
  583.     if (diff || common || neither)
  584. (void) printf ("    comparing numbers.n");
  585.     for (i = 0; i < numnums; i++)
  586. {
  587. numval = tgetnum (num[i].capname);
  588. if (use)
  589.     {
  590.     if (num[i].seenagain)
  591. {
  592. if ((numval > -1) && (numval != num[i].secondval))
  593.     {
  594.     (void) fprintf (stderr,
  595. "%s: use= order dependency found:n", progname);
  596.     (void) fprintf (stderr, "    %s: %s has %d, %s has %d.n",
  597.     num[i].capname, num[i].secondname,
  598.     num[i].secondval, nterm, numval);
  599.     }
  600. }
  601.     else
  602. {
  603. if (numval > -1)
  604.     {
  605.     num[i].seenagain = TRUE;
  606.     num[i].secondval = numval;
  607.     num[i].secondname = nterm;
  608.     if ((numval > -1) && (num[i].val != numval))
  609. num[i].changed = TRUE;
  610.     else
  611. used[n] = TRUE;
  612.     }
  613. }
  614.     }
  615. if (numval > -1)
  616.     {
  617.     if (printing != pr_none)
  618. pr_number (num[i].infoname, num[i].capname, num[i].fullname, numval);
  619.     if (common && (num[i].val == numval))
  620. (void) printf ("t%s= %d.n", num[i].infoname, numval);
  621.     }
  622. else if (neither && (num[i].val == -1))
  623.     (void) printf ("t!%s.n", num[i].infoname);
  624. if (diff && (num[i].val != numval))
  625.     (void) printf ("t%s: %d:%d.n", num[i].infoname, num[i].val,
  626.     numval);
  627. if (verbose)
  628.     (void) fprintf (trace, "%s: %d:%d,changed=%d,seen=%d.n",
  629.     num[i].infoname, num[i].val, numval,
  630.     num[i].changed, num[i].seenagain);
  631. }
  632.     if (printing != pr_none)
  633. {
  634. if (printing == pr_cap)
  635.     pr_ncaps();
  636. pr_nfooting();
  637. pr_sheading();
  638. }
  639.     if (diff || common || neither)
  640. (void) printf ("    comparing strings.n");
  641.     for (i = 0; i < numstrs; i++)
  642. {
  643. strval = tgetstr (str[i].capname, (char **)0);
  644. if (use)
  645.     {
  646.     if (str[i].seenagain && (strval != NULL))
  647. {
  648. if (!EQUAL (strval, str[i].secondval))
  649.     {
  650.     (void) fprintf (stderr, "use= order dependency found:n");
  651.     (void) fprintf (stderr, "    %s: %s has '",
  652.     str[i].capname, str[i].secondname);
  653.     PR (stderr, str[i].secondval);
  654.     (void) fprintf (stderr, "', %s has '", nterm);
  655.     PR (stderr, strval);
  656.     (void) fprintf (stderr, "'.n");
  657.     }
  658. }
  659.     else
  660. {
  661. if (strval != NULL)
  662.     {
  663.     str[i].seenagain = TRUE;
  664.     str[i].secondval = strval;
  665.     str[i].secondname = nterm;
  666.     if (!EQUAL (str[i].val, strval))
  667. str[i].changed = TRUE;
  668.     else
  669. used[n] = TRUE;
  670.     }
  671. }
  672.     }
  673. if (strval != NULL)
  674.     {
  675.     if (printing != pr_none)
  676. pr_string (str[i].infoname, str[i].capname, str[i].fullname, strval);
  677.     if (common && EQUAL (str[i].val, strval))
  678. {
  679. (void) printf ("t%s= '", str[i].infoname);
  680. PR (stdout, strval);
  681. (void) printf ("'.n");
  682. }
  683.     }
  684. else if (neither && (str[i].val == NULL))
  685.     (void) printf ("t!%s.n", str[i].infoname);
  686. if (diff && !EQUAL (str[i].val, strval))
  687.     {
  688.     (void) printf ("t%s: '", str[i].infoname);
  689.     PR (stdout, str[i].val);
  690.     (void) printf ("','");
  691.     PR (stdout, strval);
  692.     (void) printf ("'.n");
  693.     }
  694. if (verbose)
  695.     {
  696.     (void) fprintf (trace, "%s: '", str[i].infoname);
  697.     PR (trace, str[i].val);
  698.     (void) fprintf (trace, "':'");
  699.     PR (trace, strval);
  700.     (void) fprintf (trace, "',changed=%d,seen=%d.n",
  701.     str[i].changed, str[i].seenagain);
  702.     }
  703. }
  704.     if (printing == pr_cap)
  705. pr_scaps();
  706.     if (printing != pr_none)
  707. pr_sfooting();
  708. }
  709. /*
  710.     A capability gets an at-sign if it no longer exists, but
  711.     one of the relative entries contains a value for it.
  712.     It gets printed if the original value is not seen in ANY
  713.     of the relative entries, or if the FIRST relative entry that has
  714.     the capability gives a DIFFERENT value for the capability.
  715. */
  716. void dorelative (firstoptind, argc, argv)
  717. register int firstoptind;
  718. register int argc;
  719. register char **argv;
  720. {
  721.     register int i;
  722.     /* turn off printing of termcap and long names */
  723.     pr_init (pr_terminfo);
  724.     /* print out the entry name */
  725.     pr_heading ((char *)0, savettytype);
  726.     pr_bheading();
  727.     /* Print out all bools that are different. */
  728.     for (i = 0; i < numbools; i++)
  729. if (!ibool[i].val && ibool[i].changed)
  730.     pr_boolean (ibool[i].infoname, (char *)0, (char *)0, -1);
  731. else if (ibool[i].val && (ibool[i].changed || !ibool[i].seenagain))
  732.     pr_boolean (ibool[i].infoname, (char *)0, (char *)0, 1);
  733.     pr_bfooting();
  734.     pr_nheading();
  735.     /* Print out all nums that are different. */
  736.     for (i = 0; i < numnums; i++)
  737. if (num[i].val < 0 && num[i].changed)
  738.     pr_number (num[i].infoname, (char *)0, (char *)0, -1);
  739. else if (num[i].val >= 0 && (num[i].changed || !num[i].seenagain))
  740.     pr_number (num[i].infoname, (char *)0, (char *)0, num[i].val);
  741.     pr_nfooting();
  742.     pr_sheading();
  743.     /* Print out all strs that are different. */
  744.     for (i = 0; i < numstrs; i++)
  745. if (str[i].val == NULL && str[i].changed)
  746.     pr_string (str[i].infoname, (char *)0, (char *)0, (char *)0);
  747. else if ((str[i].val != NULL) &&
  748.  (str[i].changed || !str[i].seenagain))
  749.     pr_string (str[i].infoname, (char *)0, (char *)0, str[i].val);
  750.     pr_sfooting();
  751.     /* Finish it up. */
  752.     for (i = firstoptind; i < argc; i++)
  753. if (used[i - firstoptind])
  754.     (void) printf ("tuse=%s,n", argv[i]);
  755. else
  756.     (void) fprintf (stderr,
  757. "%s: 'use=%s' did not add anything to the description.n",
  758. progname, argv[i]);
  759. }
  760. void setenv (termNinfo)
  761. register char *termNinfo;
  762. {
  763.     extern char **environ;
  764.     static char *newenviron[2] = { 0, 0 };
  765.     static unsigned int termsize = BUFSIZ;
  766.     static char _terminfo[BUFSIZ];
  767.     static char *terminfo = &_terminfo[0];
  768.     register int termlen;
  769.     if (termNinfo && *termNinfo)
  770. {
  771. if (verbose)
  772.     (void) fprintf (trace, "setting TERMINFO=%s.n", termNinfo);
  773. termlen = strlen (termNinfo);
  774. if (termlen + 10 > termsize)
  775.     {
  776.     termsize = termlen + 20;
  777.     terminfo = (char *) malloc (termsize * sizeof (char));
  778.     }
  779. if (terminfo == (char *) NULL)
  780.     badmalloc();
  781. (void) sprintf (terminfo, "TERMINFO=%s", termNinfo);
  782. newenviron[0] = terminfo;
  783. }
  784.     else
  785. newenviron[0] = (char *) 0;
  786.     environ = newenviron;
  787. }
  788. main (argc, argv)
  789. int argc;
  790. char **argv;
  791. {
  792.     register int i, c, firstoptind;
  793.     char *tempargv[2];
  794.     char *term = getenv ("TERM");
  795.     term1info = term2info = getenv ("TERMINFO");
  796.     progname = argv[0];
  797.     /* parse options */
  798.     while ((c = getopt (argc, argv, "ducnILCvV1rw:s:A:B:")) != EOF)
  799. switch (c)
  800.     {
  801.     case 'v': verbose++; break;
  802.     case '1': pr_onecolumn(1); break;
  803.     case 'w': pr_width (atoi(optarg)); break;
  804.     case 'd': diff++; break;
  805.     case 'c': common++; break;
  806.     case 'n': neither++; break;
  807.     case 'u': use++; break;
  808.     case 'L': pr_init (printing = pr_longnames); break;
  809.     case 'I': pr_init (printing = pr_terminfo); break;
  810.     case 'C': pr_init (printing = pr_cap); break;
  811.     case 'A': term1info = optarg; Aflag++; break;
  812.     case 'B': term2info = optarg; Bflag++; break;
  813.     case 'r': pr_caprestrict(0); break;
  814.     case 's':
  815. if (strcmp(optarg, "d") == 0)
  816.     sortorder = by_database;
  817. else if (strcmp(optarg, "i") == 0)
  818.     sortorder = by_terminfo;
  819. else if (strcmp(optarg, "l") == 0)
  820.     sortorder = by_longnames;
  821. else if (strcmp(optarg, "c") == 0)
  822.     sortorder = by_cap;
  823. else
  824.     goto usage;
  825. break;
  826.     case 'V':
  827. (void) printf ("%s: version %sn", progname, "infocmp.c 1.10");
  828. exit (0);
  829.     case '?':
  830.     usage:
  831. (void) fprintf (stderr,
  832. "usage: %s [-ducn] [-ILC] [-1Vv] [-s d|i|l|c] [-A directory] [-B directory] term-names ...n",
  833. progname);
  834. (void) fprintf (stderr, "t-dtprint differences (the default for >1 term-name)n");
  835. (void) fprintf (stderr, "t-utproduce relative descriptionn");
  836. (void) fprintf (stderr, "t-ctprint common entriesn");
  837. (void) fprintf (stderr, "t-ntprint entries in neithern");
  838. (void) fprintf (stderr, "t-Itprint terminfo entries (the default for 1 term-name)n");
  839. (void) fprintf (stderr, "t-Ctprint termcap entriesn");
  840. (void) fprintf (stderr, "t-Ltprint long C variable namesn");
  841. (void) fprintf (stderr, "t-1tsingle column outputn");
  842. (void) fprintf (stderr, "t-Vtprint program versionn");
  843. (void) fprintf (stderr, "t-vtverbose debugging outputn");
  844. (void) fprintf (stderr, "t-stchange sort ordern");
  845. (void) fprintf (stderr, "t-Atset $TERMINFO for first term-namen");
  846. (void) fprintf (stderr, "t-Btset $TERMINFO for other term-namesn");
  847. exit (-1);
  848.     }
  849.     argc -= optind;
  850.     argv += optind;
  851.     optind = 0;
  852.     /* Default to $TERM for -n, -I, -C and -L options. */
  853.     /* This is done by faking argv[][], argc and optind. */
  854.     if (neither && (argc == 0 || argc == 1))
  855. {
  856. if (argc == 0)
  857.     tempargv[0] = term;
  858. else
  859.     tempargv[0] = argv[optind];
  860. tempargv[1] = term;
  861. argc = 2;
  862. argv = tempargv;
  863. optind = 0;
  864. }
  865.     else if ((printing != pr_none) && (argc == 0))
  866. {
  867. tempargv[0] = term;
  868. argc = 1;
  869. argv = tempargv;
  870. optind = 0;
  871. }
  872.     /* Check for enough names. */
  873.     if ((use || diff || common) && (argc <= 1))
  874. {
  875. (void) fprintf (stderr,
  876.     "%s: must have at least two terminal names for a comparison to be done.n",
  877.     progname);
  878. goto usage;
  879. }
  880.     /* Set the default of diff -d or print -I */
  881.     if (!use && (printing == pr_none) && !common && !neither)
  882. {
  883. if (argc == 0 || argc == 1)
  884.     {
  885.     if (argc == 0)
  886. {
  887. tempargv[0] = term;
  888. argc = 1;
  889. argv = tempargv;
  890. optind = 0;
  891. }
  892.     pr_init (printing = pr_terminfo);
  893.     }
  894. else
  895.     diff++;
  896. }
  897.     /* Set the default sorting order. */
  898.     if (sortorder == none)
  899. switch ((int) printing)
  900.     {
  901.     case (int) pr_cap: sortorder = by_cap; break;
  902.     case (int) pr_longnames: sortorder = by_longnames; break;
  903.     case (int) pr_terminfo:
  904.     case (int) pr_none: sortorder = by_terminfo; break;
  905.     }
  906.     firstterm = argv[optind++];
  907.     firstoptind = optind;
  908.     allocvariables (argc, firstoptind);
  909.     sortnames ();
  910.     devnull = open("/dev/null", O_RDWR);
  911.     setenv(term1info);
  912.     initfirstterm (firstterm);
  913.     setenv(term2info);
  914.     for (i = 0; optind < argc; optind++, i++)
  915. check_nth_terminal (argv[optind], i);
  916.     if (use)
  917. dorelative (firstoptind, argc, argv);
  918.     return 0;
  919. }