[comp.sources.unix] v24i086: Decompile terminfo terminal descriptions

rsalz@uunet.uu.net (Rich Salz) (03/27/91)

Submitted-by: Dave Regan <regan@jacobs.cs.orst.edu>
Posting-number: Volume 24, Issue 86
Archive-name: untic2


Enclosed is an update to "untic" which first appeared in volume 5 of
comp.sources.unix in 1986.  It takes a compiled terminfo(3) description
of a terminal and dumps it in a format comatible with infocmp so
that a new description can be added to the terminfo database.

This program is for System V machines which use the "terminfo" database,
and do not have access to the AT&T program called "infocmp".

This program has been updated to include all of the current terminal
characteristics, as well as emiting the output in a fashion that is
compatible with "infocmp".


				Dave Regan
				regan@jacobs.cs.orst.edu
-------------------------------------------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile untic.1 untic.c untic.tst
# Wrapped by regan@regan-h on Mon Dec 10 23:22:53 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(1216 characters\)
sed "s/^X//" >README <<'END_OF_README'
Xuntic -- Decompile a "terminfo" terminal description file for System V.
X
XI wrote the following program, "untic", because I needed to make a terminal
Xdescription file which was just slightly different from one of the existing
Xterminal descriptions.
X
XThis program looks up the description directly from the compiled description
Xfile.  Thus it produces a file, which when compiled, generated exactly the
Xsame information as was in the original file.
X
XThis "shar" file contains the following files:
X	README		This file
X	untic.1		A (very simple) manual page
X	Makefile	A (very simple) make file
X	untic.c		The program
X	untic.tst	A simple test script to compare against "infocmp"
X
XThis was written long ago, before "infocmp" was available.  This was
Xpublished in volume 5 of comp.sources.unix in May of 1986.  At the request
Xof Joe Wasik from the Unix/C Reusable Code Library, I have updated this
Xprogram to a more modern version of System V.  Evidentally, not all sites
Xwhich have the terminfo terminal descriptions have "infocmp".
X
XIf "infocmp" is available at your site, then this program is of no real use;
Xinfocmp does all this does, plus a whole lot more.
X
X			Dave Regan
X			10 December 1990
X			regan@jacobs.cs.orst.edu
END_OF_README
if test 1216 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(361 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
XCFLAGS = -DSYSVR3 -DSTRICT_TERMINFO_COMPATIBILITY -O
XDESTDIR = /usr/local/bin
XDOCDIR = /usr/local/man/man1
X
Xuntic:	untic.c
X	$(CC) $(CFLAGS) untic.c -o untic
X
Xlint:
X	lint untic.c
X
Xinstall:	untic
X	cp untic $(DESTDIR)/untic
X	strip $(DESTDIR)/untic
X#	cp untic.1 $(DOCDIR)/untic.1
X
Xclean:
X	rm untic
X
Xshar:
X	shar README Makefile untic.1 untic.c untic.tst >untic.shar
END_OF_Makefile
if test 361 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f untic.1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"untic.1\"
else
echo shar: Extracting \"untic.1\" \(1508 characters\)
sed "s/^X//" >untic.1 <<'END_OF_untic.1'
X.TH UNTIC 1 Public Domain
X.SH NAME
Xuntic \- Uncompile terminfo terminal description files
X.SH SYNOPSIS
X.B untic
X.B terminal_name
X[
X.B . . .
X]
X.SH DESCRIPTION
X.B untic
Xconvert the terminfo file which corresponds to the specified terminal name
Xinto a file that can be processed by
X.B tic.
X.PP
XIf multiple terminal names are given, a terminal description is generated
Xfor each of the named terminals.
XThe output is written on standard output.
X.PP
XIt is wise to backup the original terminal description
X(from /usr/lib/terminfo)
Xbefore compiling the generated file.
X.PP
XNormally, terminal descriptions are found in "/usr/lib/terminfo".
XHowever, if the environment variable "TERMINFO" exists, then
Xthe value of that variable is used as the path of terminal descriptions.
X.SH EXAMPLES
XTo uncompile the terminal description for a "vt100", type:
X.RS
Xuntic vt100 >vt100
X.RE
XTo compile this generated file, you probably need root permissions and type:
X.RS
Xtic vt100
X.RE
X.SH NOTES
XIf new capabilities are added to the terminfo database,
Xthe
X.B untic
Xprogram will need to be modified.
XWith luck, the new entries will go at the end of the appropriate tables.
X.PP
XMost of the capabilities are in the tables in the order that the capabilites
Xare documented.
XThere are a few exceptions in the string variables.
X.PP
XThis program is placed into the public domain.
XThat means that you can do anything you want to with it.
X.SH BUGS
XNone known, but . . .
X.SH FILES
XThe terminal descriptions are stored in
X.B /usr/lib/terminfo/?/*
END_OF_untic.1
if test 1508 -ne `wc -c <untic.1`; then
    echo shar: \"untic.1\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f untic.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"untic.c\"
else
echo shar: Extracting \"untic.c\" \(18844 characters\)
sed "s/^X//" >untic.c <<'END_OF_untic.c'
X/*
X * Untic.c -- Uncompile a terminfo file
X *
X * Usage:
X *	untic terminal_name . . .
X *
X * This program finds the terminal description in
X *	/usr/lib/terminfo/?/terminal_name
X * It then converts the information into an ASCII file suitable for
X * running into "tic".  The resulting file is written to standard output.
X *
X * Compile by:
X *	cc -DSYSVR3 -O -o untic untic.c
X *
X * It is probably a good idea to ensure that the file produced will compile
X * to the original file before trusting "untic".
X *
X * Structure of terminfo file:
X *	short	magic number
X *	short	length of terminal names + NUL
X *	short	length of booleans
X *	short	length of numerics
X *	short	length of strings
X *	short	length of string table
X *	chars	NUL terminated terminal name
X *	chars	boolean flags for each of the possible booleans
X *	shorts	values for each of the possible numerics
X *	shorts	offsets (from start of strings) for each of the
X *		possible strings
X *	chars	NUL terminated strings for each of the defined strings
X *
X * Most of the variables are in the order that the documentation lists
X * them.  This is important, as the information is stored in the file
X * based upon the ordinal position of the variable.  Some of the string
X * variables are not in order.  Presumably, if they add more variables,
X * it will be to the end of the list, and not in the middle.
X *
X * This has been tested on
X *	Plexus P20 (M68010), System 5 Release 2 (I think)
X *
X * Bugs:
X *	The longest string capability is limited to 4096 bytes.  If a longer
X *	string is encountered, the program will do unpredicatable things.
X *	(Who uses strings that long anyway?)  The longest that the terminfo
X *	file can be is 4096 bytes anyway, so this isn't too big a problem.
X *
X * Credits:
X *	Written by Dave Regan	orstcs!regan	16 May 86
X *	TERMINFO environment variable added by G A Moffett (amdahl!gam)
X *		31 May 86
X *	TERMINFO environment variable added by hp-pcd!hplabs!csun!aeusemrs
X *	(again) 16 Jan 87.  Time to get this out.
X *
X *	I disclaim that this program does anything useful.  It might also
X *	do accidental damage.  Backup your original terminfo files.
X *
X *	This program is public domain.  That means you can do anything
X *	you want with it.
X *
X *		New Notes		16 Jan 1987
X *	I want to thank the people who have written to me to let
X *	me know that they have a use for this program, and have added
X *	suggestions.  I am also glad that Unipress have this tool on
X *	their distribution tape.
X *
X *	It has been brought to my attention (by Tony Hansen -
X *	ihnp4!pegasus!hansen) that there is a program in the ATT toolchest
X *	and to be distributed in system V, release 3 called "infocmp" that
X *	does what "untic" does, as well as a lot more.  See the System V
X *	Administration Guide.
X *
X *			Thanks to everyone who gave me information,
X *			Dave Regan	16 Jan 87
X *
X *
X *		Notes			10 December 1990
X *	I have added the capabilities necessary to support a more modern
X *	version of System V.  To get these new capabilities, add -DSYSVR3
X *	to the command line.  In general, it should not hurt to have too many
X *	capabilities in this list, as long as it is a strict superset of
X *	what you have in your "tic".  (These changes were basically noted
X *	by Kirk Webb (kirk@ico.ISC.COM) on 13 Feb 1987.  I have added
X *	some beyond what he had called out.)
X *
X *	If it comes to figuring out why this doesn't work, run "strings -2"
X *	on the Terminfo Compiler (tic) and look at the output.  You should
X *	see the tables of capabilities go by.  Copy these capabilities
X *	into the appropriate tables, and you should be fine.
X *
X *	Some of the terminfo compilers have more symbols than others.
X *	I modified the error checking to not emit an error unless one of
X *	the "extended" symbols is actually referenced.
X *
X *	I have added "void" as a return type to some of the functions.
X *	If this gives your C compiler a fit, then do a "-Dvoid=int" on
X *	the command line.
X *
X *	Thanks to Joe Wasik at the Unix/C Reusable Code Library
X *	(jcwasik@clib.PacBell.COM) to get me to put this together
X *	again with current tables.  The test program (untic.tst) was
X *	also written by him.
X *
X *	It appears that current versions of infocmp will somehow derive
X *	the "ma#1" capability on older terminfo files.  I have looked
X *	at the various terminfo files in reasonable detail, and cannot
X *	figure out how it can tell the difference.  So I am punting,
X *	and simply enumerate all of the "special" cases.  This is a
X *	gross hack, and if anyone can tell me an algorithmic way to
X *	do this, I would apperciate it.  Actually, it does this even
X *	on "modern" terminfo files.  See "fortune" for an example of
X *	a terminfo file which could represent the "ma" capability but
X *	the value is 0xFFFF (not used).  Yet, the "ma#1" capability is
X *	printed by terminfo.  I am almost beginning to think that this
X *	is a bug on terminfo's part, but processing it correctly is so
X *	trivial, that I don't see how this could be messed up; it must
X *	be by design.  Well, if you find out, let me know.
X *
X *			Dave Regan	10 December 1990
X */
X
X#include <stdio.h>
X#include <ctype.h>
X
X#ifdef __MSDOS__
X#include <stdlib.h>
X#include <string.h>
X#define	OPEN_MODE	"rb"
X#define	CVPTR		const void
X#define	F(x)		x	/* Function prototypes			*/
X#else
Xextern char *strcpy();		/* This should be in strings.h		*/
Xextern char *	malloc();	/* This is supposed to be in stdlib.h, but
X				 * that file doesn't exist on older systems. */
X#define	OPEN_MODE	"r"	/* Mode used to open terminfo files	*/
X#define	CVPTR		char
X#define	F(x)		()	/* No prototypes			*/
X#endif	/* __MSDOS__ */
X
X/***
X ***	Local constants
X ***/
X#ifndef TRUE
X#define	TRUE	1
X#define	FALSE	0
X#endif		/* TRUE */
X
X#define	DEBUG	FALSE		/* TRUE/FALSE to enable debugging output */
X
X#ifndef TERMINFO_DIR
X#define	TERMINFO_DIR	"/usr/lib/terminfo"
X#endif		/* TERMINFO_DIR */
X
X
X#define	MAGIC	0x011A		/* Terminfo magic number		*/
X#define	MAXLINE	55		/* Longest emited line			*/
X#define	MAX_CAP	4096		/* Longest single capability		*/
X
X/***
X ***	Forward declarations
X ***/
Xextern char *	addchar F((char *cptr, int ch));
Xextern char *	addoctal F((char *cptr, int ch));
Xextern char *	addstr F((char *cptr, char *str));
Xextern void	convert F((FILE *file, char *name));
Xextern void	emit F((char *str));
Xextern unsigned short get2 F((FILE *file));
Xextern int	xstrcmp F((CVPTR *a, CVPTR *b));
X
X/***
X ***	Global data
X ***/
Xint	Line_len;		/* Current length of line		*/
X
X/***
X ***	Definitions of attributes
X ***/
Xchar	*Booleans[] =	/* Names of boolean variables, in order	*/
X	{ "bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km",
X	  "hs", "in", "da", "db", "mir", "msgr", "os", "eslok", "xt",
X	  "hz", "ul", "xon"
X#ifdef SYSVR3
X	, "nxon", "mc5i", "chts", "nrrmc", "npc"
X	, "ndscr"
X#endif	/* SYSVR3 */
X	 };
X#define	BOOL_LENGTH	(sizeof(Booleans) / sizeof(char *))
X
Xchar	*Numerics[] =	/* Names of numeric variables, in order	*/
X	{ "cols", "it", "lines", "lm", "xmc", "pb", "vt", "wsl"
X#ifdef SYSVR3
X	, "nlab", "lh", "lw"
X	, "ma", "wnum"	
X#endif	/* SYSVR3 */
X	};
X#define	NUM_LENGTH	(sizeof(Numerics) / sizeof(char *))
X
Xchar	*Strings[] =	/* Names of string variables, not in strict
X				   order.  Makes things a little harder	*/
X	{ "cbt", "bel", "cr", "csr", "tbc", "clear", "el", "ed", "hpa",
X	  "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup",
X	  "cnorm", "cuf1", "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl",
X	  "hd", "smacs", "blink", "bold", "smcup", "smdc", "dim", "smir",
X	  "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", 
X	  "rmcup", "rmdc", "rmir", "rmso", "rmul", "flash", "ff", "fsl",
X	  "is1", "is2", "is3", "if", "ich1", "il1", "ip", "kbs", "ktbc",
X	  "kclr", "kctab", "kdch1", "kdl1", "kcud1", "krmir", "kel", "ked",
X	  "kf0", "kf1", "kf10", "kf2", "kf3", "kf4", "kf5", "kf6", "kf7",
X	  "kf8", "kf9", "khome", "kich1", "kil1", "kcub1", "kll", "knp",
X	  "kpp", "kcuf1", "kind", "kri", "khts", "kcuu1", "rmkx", "smkx", 
X	  "lf0", "lf1", "lf10", "lf2", "lf3", "lf4", "lf5", "lf6", "lf7",
X	  "lf8", "lf9", "rmm", "smm", "nel", "pad", "dch", "dl", "cud",
X	  "ich", "indn", "il", "cub", "cuf", "rin", "cuu", "pfkey", "pfloc",
X	  "pfx", "mc0", "mc4", "mc5", "rep", "rs1", "rs2", "rs3", "rf",
X	  "rc", "vpa", "sc", "ind", "ri", "sgr", "hts", "wind", "ht", "tsl",
X	  "uc", "hu", "iprog", "ka1", "ka3", "kb2", "kc1", "kc3", "mc5p"
X#ifdef SYSVR3
X	, "rmp", "acsc", "pln", "kcbt", "smxon", "rmxon", "smam", "rmam",
X	  "xonc", "xoffc", "enacs", "smln", "rmln", "kbeg", "kcan", "kclo",
X	  "kcmd", "kcpy", "kcrt", "kend", "kent", "kext", "kfnd", "khlp",
X	  "kmrk", "kmsg", "kmov", "knxt", "kopn", "kopt", "kprv", "kprt",
X	  "krdo", "kref", "krfr", "krpl", "krst", "kres", "ksav", "kspd",
X	  "kund", "kBEG", "kCAN", "kCMD", "kCPY", "kCRT", "kDC", "kDL",
X	  "kslt", "kEND", "kEOL", "kEXT", "kFND", "kHLP", "kHOM", "kIC",
X	  "kLFT", "kMSG", "kMOV", "kNXT", "kOPT", "kPRV", "kPRT", "kRDO",
X	  "kRPL", "kRIT", "kRES", "kSAV", "kSPD", "kUND", "rfi", "kf11",
X	  "kf12", "kf13", "kf14", "kf15", "kf16", "kf17", "kf18", "kf19",
X	  "kf20", "kf21", "kf22", "kf23", "kf24", "kf25", "kf26", "kf27",
X	  "kf28", "kf29", "kf30", "kf31", "kf32", "kf33", "kf34", "kf35",
X	  "kf36", "kf37", "kf38", "kf39", "kf40", "kf41", "kf42", "kf43",
X	  "kf44", "kf45", "kf46", "kf47", "kf48", "kf49", "kf50", "kf51",
X	  "kf52", "kf53", "kf54", "kf55", "kf56", "kf57", "kf58", "kf59",
X	  "kf60", "kf61", "kf62", "kf63", "el1", "mgc", "smgl", "smgr",
X	  "fln", "sclk", "dclk", "rmclk", "cwin", "wingo", "hup", "dial",
X	  "qdial", "tone", "pulse", "hook", "pause", "wait", "u0", "u1",
X	  "u2", "u3", "u4", "u5", "u6", "u7", "u8", "u9"
X#endif	/* SYSVR3 */
X#ifdef HPUX5
X	  , "meml", "memu"
X#endif	/* HPUX5 */
X	  };
X#define	STR_LENGTH	(sizeof(Strings) / sizeof(char *))
X
Xchar	*Exceptions[] =
X	{ "912b", "912cc", "920b", "adm5", "d800", "dtc", "f1720", "fortune",
X	  "hp", "hp110", "intext", "ofos", "pe1251", "regent100", "regent40",
X	  "regent40-s", "regent60", "regent60-na", "sb1", "sb2", "sbi",
X	  "smartvid", "t1061", "t1061f", "tec400", "trs16", "tvi2p", "tvi803",
X	  "tvi912", "tvi912-2p", "tvi9122p", "tvi9202p", "tvi925", "tvi925-v",
X	  "tvi950", "tvi950-2p", "tvi950-4p", "tvi950-ap", "tvi950-b",
X	  "tvi950-ns", "tvi950-rv", "tvi950-rv-2p", "tvi950-rv-4p",
X	  "tvi9502p", "tvi9504p", "tvi950b", "tvi950ns", "tvi950rv",
X	  "tvi950rv2p", "tvi950rv4p", "vt100-nav", "vt100-nav-w", "xtalk",
X	  "ya", NULL
X	};
X
X/***
X ***	Function definitions
X ***/
X
Xvoid
Xmain(argc, argv)
X  int	argc;			/* Number of paramters			*/
X  char	*argv[];		/* The parameters themselves		*/
X    {
X    char subdir[2];		/* Subdirectory name			*/
X    FILE *file;
X    char *terminfo;
X    extern FILE *fopen();
X    extern char *getenv();
X
X    /* Change directory to the working directory			*/
X    terminfo = getenv("TERMINFO");
X    if (terminfo == NULL) {
X 	terminfo = TERMINFO_DIR;
X    }
X#if DEBUG
X    fprintf(stderr, "Looking in %s/?/... for entry.\n", terminfo);
X#endif
X    (void)chdir(terminfo);
X
X    /* Go through the arguments						*/
X    subdir[1] = '\0';
X    if (argc == 1)
X	convert(stdin, "stdin");
X    else
X	{
X	while (--argc)
X	    {
X	    ++argv;
X	    subdir[0] = argv[0][0];
X	    (void)chdir(subdir);
X	    if ((file = fopen(*argv, OPEN_MODE)) == NULL)
X		{
X		perror(*argv);
X		}
X	    else
X		{
X		convert(file, *argv);
X		(void)fclose(file);
X		}
X	    (void)chdir("..");
X	    }
X	}
X    exit(0);
X    }
X
X
X/*
X * Addchar -- Add a character
X */
Xchar *
Xaddchar(cptr, ch)
X  char	*cptr;
X  int	ch;
X    {
X    char *addstr(), *addoctal();
X
X    if (ch == '\0')
X	return (addstr(cptr, "\\200"));
X    if (ch == 0x1B)
X	return (addstr(cptr, "\\E"));
X    if (ch == '\n')
X	return (addstr(cptr, "\\n"));
X    if (ch == '\r')
X	return (addstr(cptr, "\\r"));
X    if (ch == '\t')
X	return (addstr(cptr, "\\t"));
X    if (ch == '\b')
X	return (addstr(cptr, "\\b"));
X    if (ch == '\f')
X	return (addstr(cptr, "\\f"));
X    if (ch == ' ')
X	return (addstr(cptr, "\\s"));
X    if (ch == '^')
X	return (addstr(cptr, "\\^"));
X    if (ch == '\\')
X	return (addstr(cptr, "\\\\"));
X    if (ch == ',')
X	return (addstr(cptr, "\\,"));
X    if (ch == 0x7F)
X	return (addstr(cptr, "\^?"));
X    if (ch >= ('A' - '@') && ch <= ('_' - '@'))
X	{
X	*cptr++ = '^';
X	*cptr++ = ch + '@';
X	return (cptr);
X	}
X    if (ch > 0x7F)
X    	return (addoctal(cptr, ch));
X    *cptr++ = ch;
X    return (cptr);
X    }
X
X
X/*
X * Addoctal -- Add an octal character
X *
X * Use sprintf just in case "0" through "7" are not contiguous.  Some
X * machines are weird.
X */
Xchar *
Xaddoctal(cptr, ch)
X  char	*cptr;
X  int	ch;
X    {
X    char *addstr();
X
X    ch &= 0xFF;
X
X    if (ch == 0x80)
X	return (addstr(cptr, "\\200"));
X    (void)sprintf(cptr, "\\%03o", ch);
X    while (*cptr != '\0')
X	cptr++;
X    return (cptr);
X    }
X
X
X/*
X * Addstr -- Add a string to the capability
X */
Xchar *
Xaddstr(cptr, str)
X  char	*cptr, *str;
X    {
X    while (*str)
X	*cptr++ = *str++;
X    return (cptr);
X    }
X
X
X/*
X * Convert -- Do the actual conversion
X */
Xvoid
Xconvert(file, name)
X  FILE	*file;		/* The file with the compiled information	*/
X  char	*name;		/* Printable version of the filename		*/
X    {
X    int	ch, val, i, j;
X    int name_length, bool_length, num_length, str_length, s_length;
X    char capability[MAX_CAP+1], *cptr, *addchar();
X    char **scan;
X    char term_name[80];
X    int str_cap[STR_LENGTH];
X
X    /* Check the magic number out					*/
X    if (get2(file) != MAGIC)
X	{
X	fprintf(stderr, "\"%s\" is not a terminfo file\n", name);
X	return;
X	}
X
X    /* Get the rest of the header information				*/
X    name_length = get2(file);	/* Get the length of the terminal names	*/
X    bool_length = get2(file);	/* Get the length of the booleans	*/
X    num_length = get2(file);	/* Get the length of the numerics	*/
X    str_length = get2(file);	/* Get the length of the strings	*/
X    s_length = get2(file);	/* Get the length of the string tables	*/
X
X    /* Time to get real information					*/
X    cptr = term_name;
X    while ((ch = getc(file)) != '\0' && ch != EOF)
X	{
X	if (cptr != NULL)
X	    {
X	    if (ch == '|')
X		{
X		*cptr = '\0';
X		cptr = NULL;
X		}
X	    else
X		*cptr++ = ch;
X	    }
X	putchar(ch);
X	}
X    if (cptr != NULL)
X	*cptr = '\0';
X    printf(",\n");
X
X    /* Send out the non-null boolean variables				*/
X    Line_len = 0;
X    for (i = 0; i < bool_length; i++)
X	{
X	if ((ch = getc(file)) != 0)
X	    {
X	    if (i < BOOL_LENGTH)
X		emit(Booleans[i]);
X	    else
X		fprintf(stderr, "Undefined boolean capability #%d\n", i);
X	    }
X	}
X    emit((char *) NULL);	/* Force output */
X
X    /* The rest of the file is on a 16 bit boundary, so adjust the file	*/
X    if ((name_length + bool_length) & 0x01)
X	(void)getc(file);
X
X#ifdef STRICT_TERMINFO_COMPATIBILITY
X    /* Bozo alert!!!  It appears that there is special code in infocmp to
X     * put out ma#1 if this is a special terminfo file.  Presumably this
X     * is a good default.  Definitately odd.
X     */
X    for (scan = Exceptions;
X			*scan != NULL && strcmp(*scan, term_name) != 0; scan++)
X	;
X    if (*scan != NULL)
X	emit("ma#1");
X    /* End bozo alert */
X#endif	/* STRICT_TERMINFO_COMPATIBILITY */
X
X    /* Get the numeric variables					*/
X    for (i = 0; i < num_length; i++)
X	{
X	if ((val = get2(file)) != 0xFFFF)
X	    {
X	    if (i < NUM_LENGTH)
X		{
X		(void)sprintf(capability, "%s#%d", Numerics[i], val);
X		emit(capability);
X		}
X	    else
X		{
X		fprintf(stderr, "Undefined numeric capability #%d (%d)\n",
X						i, val);
X		}
X	    }
X	}
X    emit((char *) NULL);	/* Force output */
X
X    /* Get the string variables offsets					*/
X    for (i = 0; i < str_length; i++)
X	str_cap[i] = get2(file);
X
X    /* Get the string variables themselves				*/
X    for (i = 0; i < s_length; i++)
X	{
X	for (j = 0; j < str_length; j++)	/* Find the name	*/
X	    if (str_cap[j] == i)
X		break;
X	if (j >= str_length)
X	    {
X#if DEBUG
X	    fprintf(stderr, "Cannot find address %d\n", i);
X#endif		/* DEBUG */
X	    (void)getc(file);
X	    continue;
X	    }
X	if (j < STR_LENGTH)
X	    (void)strcpy(capability, Strings[j]);
X	else
X	    (void) strcpy(capability, "OOPS");
X	cptr = &capability[strlen(capability)];
X	*cptr++ = '=';
X	for (; (ch = getc(file)) != '\0' && ch != EOF; i++)
X	    cptr = addchar(cptr, ch);
X	*cptr = '\0';
X	emit(capability);
X	if (j >= STR_LENGTH)
X	    {
X	    fprintf(stderr, "Undefined string capability #%d (%s)\n",
X							j, &capability[5]);
X	    }
X	}
X    emit((char *) NULL);	/* Force output */
X    }
X
X
X/*
X * Emit -- Emit the string
X *
X * Emit the given string, and append a comma.  If the line gets too long,
X * send out a newline and a tab.
X *
X * In order to make the output to be more directly comparable to infocmp,
X * save up all of the output for a category, sort it, and then write it out.
X */
Xvoid
Xemit(str)
X  char	*str;		/* String to emit				*/
X    {
X#ifdef SIMPLE_OUTPUT
X    if (str == NULL)
X	{
X	Line_len = 0;
X	printf("\n");
X	}
X    else
X	{
X	if (Line_len == 0)
X	    printf("\t");
X	if ((Line_len += strlen(str) + 2) > MAXLINE)
X	    {
X	    Line_len = strlen(str) + 2;
X	    printf("\n\t");
X	    }
X	printf("%s, ", str);
X	}
X#else	/* SIMPLE_OUTPUT */
X	/* Array is over large, but will be enough */
X    static char		*table[STR_LENGTH + BOOL_LENGTH + NUM_LENGTH];
X    static int		next = 0;
X
X    int			len;
X    int			scan;
X
X    if (str != NULL)
X	{
X	if ((table[next] = (char *) malloc(strlen(str) + 1)) == NULL)
X	    {
X	    fprintf(stderr, "OUT OF MEMORY\n");
X	    exit(1);
X	    }
X	strcpy(table[next++], str);
X	}
X    else if (next > 0)
X	{
X	/* strcmp isn't quite the right type, but should work */
X	qsort(table, next, sizeof(char *), xstrcmp);
X	printf("\t");
X	for (Line_len = scan = 0; scan < next; scan++)
X	    {
X	    len = strlen(table[scan]) + 2;
X	    if ((Line_len += len) > MAXLINE)
X		{
X		Line_len = len;
X		printf("\n\t");
X		}
X	    else if (Line_len != len)
X		printf(" ");
X	    printf("%s,", table[scan]);
X	    free(table[scan]);
X	    }
X	printf("\n");
X	next = 0;
X	}
X#endif	/* SIMPLE_OUTPUT */
X    }
X
X
X/*
X * Get2 -- Get a two byte number
X */
Xunsigned short
Xget2(file)
X  FILE *file;		/* The file with the compiled information	*/
X    {
X    unsigned short		temp;
X
X    temp = getc(file) & 0xFF;
X    return (temp + (getc(file) << 8));
X    }
X
X
X/*
X * Xstrcmp -- Compare function for qsort
X *
X * Infocmp only compares the base string.  Strip of equals signs.
X * This routine is an awful hack.  There is probably a more elegant
X * way of doing this with standard routines.  One possibility would
X * be to put a NUL at a possible '=', and restore it later (if one was
X * destroyed).  Call strcmp in between.
X */
Xint
Xxstrcmp(a, b)
X  CVPTR			*a;
X  CVPTR			*b;
X    {
X    char		*str1, *str2;
X
X    str1 = *(char **) a;
X    str2 = *(char **) b;
X
X    while (*str1 != '\0' && *str1 != '=' &&
X	   *str2 != '\0' && *str2 != '=' &&
X	   *str1 == *str2)
X	{
X	str1++;
X	str2++;
X	}
X    if ((*str1 == '\0' || *str1 == '=') &&
X				(*str2 == '\0' || *str2 == '='))
X	return (0);
X    if (*str1 == '\0' || *str1 == '=')
X	return (-1);
X    if (*str2 == '\0' || *str2 == '=')
X	return (1);
X    return (*str1 - *str2);
X    }
X
END_OF_untic.c
if test 18844 -ne `wc -c <untic.c`; then
    echo shar: \"untic.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f untic.tst -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"untic.tst\"
else
echo shar: Extracting \"untic.tst\" \(2035 characters\)
sed "s/^X//" >untic.tst <<'END_OF_untic.tst'
X# List of file comes from stdin
X# Get list with "find /usr/lib/terminfo -type f -print | sort > tlist"
X#
X# Written by: Joe Wasik, Unix/C Reusable Code Library
X#	      jcwasik@clib.PacBell.COM
X#
X# This compares the output of "infocmp" with "untic" for all files in the
X# terminfo library.  If this does not report major problems, then "untic"
X# is in working order for your machine.
X#
X# Of course, if you can run this script, then you have infocmp, and really
X# don't need this program.
X#
X# Use this lib as input
XTERMINFO=/usr/lib/terminfo
X# Put temp files here
XTMP=/tmp/untic$$
X# Remove all temp files
Xtrap "rm -f ${TMP} ${TMP}a infocmp.fil untic.fil; exit" 0 1 2 3
X# Create check file
X>${TMP}
X# Read through each entry
Xwhile read FILEPATH
Xdo
X    # get filename part
X    BASENAME=`basename $FILEPATH`
X    # tell user where we are
X    echo FILE:$BASENAME '\c'
X    # create file as base for comparison
X    /usr/bin/infocmp $BASENAME > ${TMP}a
X    if [ $? -ne 0 ]
X    then
X	echo "infocmp failed"
X	continue 
X    fi
X    # get line 1 from infocmp file
X    LINE1=`cat ${TMP}a | line`
X    # get item1 from line1 from infocmp file
X    TERM=`echo $LINE1 | cut -f1 -d\|`
X    # tell user term name
X    echo TERM:$TERM '\c'
X    # see if already checked
X    grep "^$TERM$" ${TMP} > /dev/null 2>&1
X    if [ $? -eq 0 ]
X    then
X	echo 'already checked'
X	continue
X    fi
X    # tell user this is a new one
X    echo 'checking...'
X    # write new term to checked list
X    echo $TERM >> $TMP
X    # from infocmp file, convert all entries to multi-line sorted
X    # with no spaces or tabs.
X    cat ${TMP}a | 
X	sed -e 's/,/\
X	/g' -e 's/[ 	]//g' | sed -e '/^$/d' | sort > infocmp.fil
X    # do same with untic output as we did with infocmp output
X    ./untic $BASENAME | 
X	sed -e 's/,/\
X	/g' -e 's/[ 	]//g' | sed -e '/^$/d' | sort > untic.fil
X    if [ $? -ne 0 ]
X    then
X	echo "untic failed"
X	continue 
X    fi
X    # do comparison -- allow diff to write to standard out
X    diff infocmp.fil untic.fil
Xdone
Xecho
Xecho "-- done --"
Xexit 0
X# @(#)untic.tst	UCLID 1.1
END_OF_untic.tst
if test 2035 -ne `wc -c <untic.tst`; then
    echo shar: \"untic.tst\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.